varnish_rest_api 0.0.4

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: 51ea11f88e1b5c03c9bf2ff42432c4eb14f6c10b
4
+ data.tar.gz: cf4faad7e206ec9cdf52ee40379593f7070689bd
5
+ SHA512:
6
+ metadata.gz: 9e3e2e865b03b00495ad4e4e12db73943a2967776d76881f866308ca79ed3ac5794f74350b5e61e5d77d90dbae9e7fbe58209ed78f88f7073af69e9a5843bc7d
7
+ data.tar.gz: 782a08d98d20563567b1ab9b26b35f07307e882332c087f7d984e71c12be5cf6f099614c6485698f10e8e76f08c479a468f1f1bd5a8b2ddca85fb6f445fa9fcb
data/.buildpath ADDED
@@ -0,0 +1,5 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <buildpath>
3
+ <buildpathentry kind="src" path=""/>
4
+ <buildpathentry kind="con" path="org.eclipse.dltk.launching.INTERPRETER_CONTAINER"/>
5
+ </buildpath>
data/.gitignore ADDED
@@ -0,0 +1,15 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
15
+ .project
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in varnish_rest_api.gemspec
4
+ gemspec
data/Gemfile.orig ADDED
@@ -0,0 +1,12 @@
1
+ source 'http://rubygems.org'
2
+
3
+ gem 'json'
4
+ gem 'rest-client'
5
+ gem 'sinatra'
6
+ gem 'zk'
7
+
8
+ group :development do
9
+ gem 'rerun'
10
+ gem 'thin'
11
+ end
12
+
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2015 Jonathan Colby
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,208 @@
1
+ # varnish-rest-api
2
+
3
+ ## Overview
4
+
5
+ A small RESTful HTTP API for [Varnish](<https://www.varnish-cache.org>) written with [Sinatra](<http://www.sinatrarb.com/intro.html>). It is designed to be run on the varnish node(s) since it executes varnishadm on the varnish node itself. It can be started as a stand-alone server using Thin, or as a rack-aware application.
6
+
7
+ #### Features
8
+
9
+ * REST calls output JSON
10
+ * (optional) use zookeeper to register varnish nodes
11
+ * configurable with a yaml configuration file and sane defaults
12
+
13
+
14
+ ## Getting Started
15
+
16
+ ### Installing
17
+
18
+ *NOTE: It is recommended to use a ruby version manager such as [rvm](<https://rvm.io/>) instead of installing with the system ruby. With a ruby version manager, you can prevent "contaminating" your system-level ruby installation by creating an isolated ruby environment independent of system-installed ruby libraries. Plus, on some systems, installing gems at the system level may require root privileges.*
19
+
20
+ ```
21
+ gem install varnish_rest_api
22
+ ```
23
+
24
+ ### Configuration
25
+
26
+ Configuration settings are stored in a file called **varnish_rest_api.yaml**. The default, example configuration can be found in the [github](<https://github.com/joncolby/varnish_rest_api/tree/master/lib>) repo or on your local system in the installed gem location.
27
+
28
+ This file is search for in the following paths in this order. The first file found is used:
29
+
30
+ * **/etc/varnish_rest_api.yaml**
31
+ * **HOME-DIR-OF-PROCESS-USER/varnish_rest_api.yaml**
32
+ * **GEMFILE-PATH/lib/varnish_rest_api.yaml**
33
+
34
+ To locate and copy the default yaml configuration:
35
+
36
+ ```
37
+ $gem contents varnish_rest_api |grep yaml$
38
+ ..
39
+ /usr/lib/ruby/gems/1.8/gems/varnish_rest_api-0.0.2/lib/varnish_rest_api.yaml
40
+ ..
41
+
42
+ $cp /usr/lib/ruby/gems/1.8/gems/varnish_rest_api-0.0.2/lib/varnish_rest_api.yaml ~/
43
+
44
+ ```
45
+
46
+ copy the secret file:
47
+
48
+ ```
49
+ sudo cp /etc/varnish/secret ~
50
+ sudo chown <username> ~/secret
51
+ sudo chmod 0600 ~/secret
52
+ ```
53
+
54
+ *(defaults configured in the application)*
55
+ ```
56
+ ---
57
+ port: 10001 <-- port server will run on (standalone mode)
58
+ bind_ip: '0.0.0.0' <-- this will bind the server to all interfaces (standalone mode)
59
+ secret: /etc/varnish/secret <-- IMPORTANT. This must be a valid,readable path to the varnish "secret" file
60
+ mgmt_port: 6082 <-- varnish management port
61
+ mgmt_host: localhost <-- varnish management ip
62
+ varnishadm_path: /usr/bin/varnishadm <-- path to varnishadm binary
63
+ instance: default <-- if more than one instance configured, specify instance name
64
+ use_zookeeper: false <-- zookeeper can be used to report available vanrish nodes
65
+ zookeeper_host: zookeeper_host:2181
66
+ zookeeper_basenode: /varnish
67
+ ```
68
+
69
+
70
+ ### Running
71
+
72
+
73
+ #### Standalone executable
74
+
75
+ An executable script is included in the gem and will be added to your $PATH after installation. The standalone executable uses Thin/WEBrick.
76
+
77
+ ```
78
+ $ varnishrestapi.rb
79
+
80
+ using configuration file: /home/vagrant/.rvm/gems/ruby-2.2.1@gemtest/gems/varnish_rest_api-0.0.2/lib/varnish_rest_api.yaml
81
+ varnishadm command line: /usr/bin/varnishadm -T localhost:6082 -S /home/vagrant/secret
82
+ [2015-03-27 14:17:58] INFO WEBrick 1.3.1
83
+ [2015-03-27 14:17:58] INFO ruby 2.2.1 (2015-02-26) [x86_64-linux]
84
+ == Sinatra (v1.4.6) has taken the stage on 10001 for development with backup from WEBrick
85
+ [2015-03-27 14:17:58] INFO WEBrick::HTTPServer#start: pid=14591 port=10001
86
+ ```
87
+
88
+ #### Rackup
89
+
90
+ create a config.ru file with the following contents:
91
+
92
+ ```
93
+ require 'rubygems'
94
+ require 'sinatra'
95
+ set :environment, ENV['RACK_ENV'].to_sym
96
+ disable :run, :reload
97
+ require 'varnish_rest_api'
98
+ run VarnishRestApi
99
+ ```
100
+
101
+ Start server with the rackup command:
102
+
103
+ ```
104
+ $ rackup -p10001 --host 0.0.0.0 config.ru
105
+ using configuration file: /etc/varnish_rest_api.yaml
106
+ varnishadm command line: /usr/bin/varnishadm -T localhost:6082 -S /home/vagrant/secret
107
+ Thin web server (v1.6.3 codename Protein Powder)
108
+ Maximum connections set to 1024
109
+ Listening on 0.0.0.0:10001, CTRL+C to stop
110
+ 192.168.33.1 - - [28/Mar/2015:14:36:18 +0000] "GET / HTTP/1.1" 200 1905 0.0199
111
+ ```
112
+ #### Example using Nginx/Passenger
113
+
114
+ Install nginx with passenger support. Excellent documentation available here: [Passenger documentation](<https://www.phusionpassenger.com/documentation/Users%20guide%20Nginx.html#bundler_support>) and [nginx centos how-to](<https://www.digitalocean.com/community/tutorials/how-to-compile-nginx-from-source-on-a-centos-6-4-x64-vps>)
115
+
116
+ ##### Concise How-to (nginx yum installation method)
117
+
118
+ Install passenger gem:
119
+
120
+ ```
121
+ $gem install passenger
122
+ ```
123
+
124
+ configure passenger support for nginx with provided script:
125
+
126
+ ```
127
+ $passenger-install-nginx-module
128
+ ```
129
+
130
+ create the following directory structure for the application:
131
+
132
+ ```
133
+ /var/www/varnishapi
134
+ |
135
+ +-- config.ru <-- see rackup example above for contents
136
+ |
137
+ +-- public/
138
+ |
139
+ +-- tmp/
140
+ ```
141
+
142
+ make sure these lines are in your nginx.conf:
143
+
144
+ ```
145
+ ...
146
+ http {
147
+
148
+ types_hash_bucket_size 64;
149
+ server_names_hash_bucket_size 128;
150
+
151
+ passenger_root /home/vagrant/.rvm/gems/<your-active-rvm-ruby>/gems/passenger-5.0.5;
152
+ passenger_ruby /home/vagrant/.rvm/gems/<your-active-rvm-ruby>/wrappers/ruby
153
+ ...
154
+
155
+ ...
156
+ server {
157
+ listen 80;
158
+ server_name localhost;
159
+
160
+ root /var/www/varnishapi/public;
161
+ passenger_enabled on;
162
+ ...
163
+ ```
164
+
165
+ start nginx and verify running processes:
166
+
167
+ ```
168
+ $ passenger-memory-stats
169
+ ...
170
+ ----- Passenger processes -----
171
+ PID VMSize Private Name
172
+ -------------------------------
173
+ 14717 351.3 MB 0.9 MB PassengerAgent watchdog
174
+ 14720 628.9 MB 1.4 MB PassengerAgent server
175
+ 14725 222.9 MB 0.8 MB PassengerAgent logger
176
+ 14741 285.7 MB 2.2 MB Passenger AppPreloader: /var/www/varnishapi
177
+ 14761 354.4 MB 12.2 MB Passenger RubyApp: /var/www/varnishapi/public
178
+ 14768 354.5 MB 9.8 MB Passenger RubyApp: /var/www/varnishapi/public
179
+ 14775 352.6 MB 2.3 MB Passenger RubyApp: /var/www/varnishapi/public
180
+ ...
181
+ ```
182
+
183
+ ### Usage Documentation
184
+ The usage documentation is available at the root context:
185
+
186
+ ```
187
+ http://your-ip-address:10001/
188
+ ```
189
+
190
+ ### WORD OF WARNING!
191
+
192
+ This small web application is meant to run in an controlled environment and offers no encryption or authentication. Anyone who can access the Rest API can potentially remove all of your varnish backends or overload your vanish process with calls to the "varnishadm" command. Use at your own risk!
193
+
194
+
195
+
196
+ ### RESTful API Actions
197
+
198
+
199
+
200
+ | Method | Url | Description | Remarks |
201
+ |------|------|------|------|
202
+ | GET | /list | list all backends | read-only |
203
+ | GET | /ping | ping varnish process | read-only |
204
+ | GET | /banner | display varnish banner with version information | read-only |
205
+ | GET | /status | display status of varnish process | read-only |
206
+ | GET | /ban | ban all objects immediately | effectively purges objects. See varnish [documentation](<https://www.varnish-cache.org/docs/3.0/tutorial/purging.html>) |
207
+ | GET | /*backend*/in | sets backend health to "auto", allowing probe to decide if backend is healthy | use partial or complete backend name as it appears in VCL. The Rest API will not process request if more than one backend is found matching for the pattern |
208
+ | GET | /*backend*/out | sets backend health to "sick" | use partial or complete backend name as it appears in VCL. The Rest API will not process request if more than one backend is found matching for the pattern|
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'varnish_rest_api'
4
+
5
+ VarnishRestApi.run!
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'sinatra'
3
+
4
+ set :environment, ENV['RACK_ENV'].to_sym
5
+ disable :run, :reload
6
+
7
+ require 'varnish_rest_api'
8
+
9
+ run VarnishRestApi
@@ -0,0 +1,199 @@
1
+
2
+ require 'open3'
3
+ require 'json'
4
+ require 'ostruct'
5
+ require 'zk'
6
+ require 'socket'
7
+
8
+
9
+ class VarnishBase
10
+
11
+ def initialize(params = {})
12
+ @mgmt_port = params.fetch(:mgmt_port, 6082)
13
+ @mgmt_host = params.fetch(:mgmt_host, 'localhost')
14
+ @instance = params.fetch(:instance, 'default')
15
+ @use_zookeeper = params.fetch(:use_zookeeper, false)
16
+ @zookeeper_host = params.fetch(:zookeeper_host, nil)
17
+ @zookeeper_basenode = params.fetch(:zookeeper_basenode, '/varnish')
18
+ @secret = params.fetch(:secret, '/etc/varnish/secret')
19
+ @varnishadm_path = params.fetch(:varnishadm_path, '/usr/bin/varnishadm')
20
+ @varnishadm = "#{@varnishadm_path.to_s} -T #{@mgmt_host.to_s}:#{@mgmt_port.to_s} -S #{@secret.to_s}"
21
+ @hostname = Socket.gethostname
22
+
23
+ puts "varnishadm command line: " + @varnishadm.to_s
24
+
25
+ if @use_zookeeper && !@zookeeper_host.empty?
26
+ puts "configured to use use zookeeper"
27
+ begin
28
+ @zk = ZK.new(@zookeeper_host)
29
+ rescue RuntimeError => e
30
+ abort "problem connecting to zookeeper host: #{@zookeeper_host}"
31
+ end
32
+
33
+ begin
34
+ @zk.create(@zookeeper_basenode + '/' + @hostname, @hostname, :mode => :ephemeral_sequential)
35
+ rescue ZK::Exceptions::NoNode => zke
36
+ @zk.create(@zookeeper_basenode,'', :mode => :persistent)
37
+ end
38
+ end
39
+
40
+ end
41
+
42
+ def output(result)
43
+ result[:error].empty? ? result[:output] : result[:error]
44
+ end
45
+
46
+ def varnish_major_version
47
+ varnishadm("banner")[:output].each do |d|
48
+ m = /^varnish-([0-9]+).*/.match(d)
49
+ unless m.nil?
50
+ return m[1].to_i
51
+ end
52
+ end
53
+ return 0
54
+ end
55
+
56
+ # banning has the effect of purging content
57
+ # https://www.varnish-software.com/static/book/Cache_invalidation.html#banning
58
+ def ban_all
59
+ command = varnish_major_version >= 4 ? '\'ban req.url ~ .\'' : '\'ban.url .\''
60
+ result = output(varnishadm(command))
61
+ JSON.pretty_generate({ command => result.empty? ? "command successful" : result })
62
+ end
63
+
64
+ # ping
65
+ def ping
66
+ JSON.pretty_generate({ 'ping' => output(varnishadm("ping")) })
67
+ end
68
+
69
+ # backend enable/disable
70
+ def set_health(backend,health,options={})
71
+ default_options = {
72
+ :safe => true,
73
+ :json => false
74
+ }
75
+ options = default_options.merge!(options)
76
+
77
+ unless ["sick","auto"].include?(health)
78
+ error = { 'error' => "invalid health '#{health}'. health must be 'sick' or 'auto'"}
79
+ return options[:json] ? JSON.pretty_generate(error) : error
80
+ end
81
+
82
+ backends_found = list_backends(:expression => backend)
83
+
84
+ if options[:safe] && backends_found.size > 1
85
+ error = { 'error' => "multiple backends found for pattern '#{backend}': " + backends_found.collect { |b| b.backend_name }.join(',')}
86
+ return options[:json] ? JSON.pretty_generate(error) : error
87
+ end
88
+
89
+ varnishadm("backend.set_health #{backend} #{health}")
90
+ list_backends(:expression => backend, :json => options[:json])
91
+ end
92
+
93
+ # list backends
94
+ def list_backends(options={})
95
+ default_options = {
96
+ :expression => nil,
97
+ :json => false
98
+ }
99
+ options = default_options.merge!(options)
100
+ backends = Array.new
101
+ command = "backend.list"
102
+
103
+ unless options[:expression].nil? || options[:expression].empty?
104
+ command += " #{options[:expression]}"
105
+ end
106
+
107
+ varnishadm_result = varnishadm(command)
108
+ #puts "command => " + command
109
+
110
+ unless varnishadm_result[:error].empty?
111
+ return options[:json] ? JSON.pretty_generate(varnishadm_result[:error]) : varnishadm_result[:error]
112
+ end
113
+
114
+ varnishadm_result[:output].to_a.each_with_index do |line,i|
115
+ #varnishadm(command)[:output].to_a.each_with_index do |line,i|
116
+ next if i < 1
117
+ backend = OpenStruct.new
118
+ #server1(127.0.0.1,80) 1 probe Sick 0/5
119
+ #line = "server1(127.0.0.1,80) 1 probe Sick 0/5"
120
+ components = line.squeeze.split
121
+ host_re = /(.*?)\((.*?)\)\s+(\d+)\s+(.*?)\s+(.*)/
122
+ match = host_re.match(line)
123
+ backend.backend_name = match[1].to_s
124
+ backend.host = match[2].to_s
125
+ backend.refs = match[3].to_s
126
+ backend.admin = match[4].to_s
127
+ backend.health = match[5].to_s
128
+ backends << backend
129
+ end
130
+ options[:json] ? JSON.pretty_generate(backends.map { |o| Hash[o.each_pair.to_a] }) : backends
131
+ end
132
+
133
+ # Display the varnish banner
134
+ def banner
135
+ JSON.pretty_generate({ 'banner' => output(varnishadm("banner"))})
136
+ end
137
+
138
+ # Display the current status of the varnish process
139
+ def status
140
+ JSON.pretty_generate({ 'status' => output(varnishadm("status"))})
141
+ end
142
+
143
+ # Run the varnishadm command and capture and return stdout,stderr
144
+ def varnishadm(cmd)
145
+ output = Array.new
146
+ error = Array.new
147
+ begin
148
+ Open3.popen3(@varnishadm + ' ' + cmd) do |stdin, stdout, stderr, wait_thr|
149
+
150
+ exit_status = wait_thr.value
151
+
152
+ unless exit_status.success?
153
+ #raise
154
+ $stderr.puts "varnishadm exited with code #{exit_status.exitstatus}"
155
+ while line = stderr.gets
156
+ $stderr.puts line
157
+ if line.strip.length > 0
158
+ error << line.strip
159
+ end
160
+ end
161
+ end
162
+
163
+ while line = stdout.gets
164
+ if line.strip.length > 0
165
+ output << line.strip
166
+ end
167
+ end
168
+ end
169
+
170
+ rescue Errno::ENOENT => e
171
+ $stderr.puts "error running varnishadm: #{e.message}"
172
+ error << "error running varnishadm: #{e.message}"
173
+ output << "error running varnishadm: #{e.message}"
174
+ end
175
+
176
+ return { :output => output, :error => error}
177
+ end
178
+
179
+ def to_s
180
+ "instance #{@instance}"
181
+ end
182
+
183
+ private :varnishadm, :varnish_major_version, :output
184
+
185
+ end
186
+
187
+
188
+ =begin
189
+ v = Varnish.new
190
+ puts v.status
191
+ puts "="
192
+ puts v.banner
193
+ puts "="
194
+ puts v.list_backends(:expression => "server3", :json=>true)
195
+ puts "="
196
+ puts v.list_backends
197
+ =end
198
+
199
+
@@ -0,0 +1,3 @@
1
+ module VarnishRestApi
2
+ VERSION = "0.0.4"
3
+ end
@@ -0,0 +1,152 @@
1
+ require 'sinatra/base'
2
+ require 'varnish_rest_api/varnish_base'
3
+ require 'yaml'
4
+
5
+ class VarnishRestApi < Sinatra::Application
6
+
7
+ CONFIG_FILE = "varnish_rest_api.yaml"
8
+ CONFIG_PATHS = [ '/etc/' + CONFIG_FILE, ENV['HOME'] + '/' + CONFIG_FILE , File.dirname(__FILE__) + '/' + CONFIG_FILE ]
9
+ CONFIG = CONFIG_PATHS.detect {|config| File.file?(config) }
10
+
11
+ if !CONFIG
12
+ $stderr.puts "no configuration file found in paths: " + CONFIG_PATHS.join(',')
13
+ exit!
14
+ else
15
+ puts "using configuration file: " + CONFIG
16
+ end
17
+
18
+ config_parsed = begin
19
+ YAML.load(File.open(CONFIG))
20
+ rescue ArgumentError, Errno::ENOENT => e
21
+ $stderr.puts "Exception while opening yaml config file: #{e}"
22
+ exit!
23
+ end
24
+
25
+ config_file = Hash.new
26
+ begin
27
+ config_file = config_parsed.inject({}){|h,(k,v)| h[k.to_sym] = v; h}
28
+ rescue NoMethodError => e
29
+ $stderr.puts "error parsing configuration yaml"
30
+ end
31
+
32
+ # default configuration
33
+ config_default = {
34
+ :bind_ip => '0.0.0.0',
35
+ :port => 4567,
36
+ :mgmt_port => 6082,
37
+ :mgmt_host => 'localhost',
38
+ :secret => '/etc/varnish/secret',
39
+ :varnishadm_path => '/usr/bin/varnishadm',
40
+ :instance => "default",
41
+ :use_zookeeper => false,
42
+ :zookeeper_host => nil,
43
+ :zookeeper_basenode => '/varnish'
44
+ }
45
+
46
+ config = config_default.merge!(config_file)
47
+
48
+ varnish = VarnishBase.new(:instance => config[:instance], \
49
+ :zookeeper_host => config[:zookeeper_host], \
50
+ :use_zookeeper => config[:use_zookeeper], \
51
+ :zookeeper_basenode => config[:zookeeper_basenode], \
52
+ :secret => config[:secret], \
53
+ :mgmt_port => config[:mgmt_port], \
54
+ :mgmt_host => config[:mgmt_host], \
55
+ :varnishadm_path => config[:varnishadm_path])
56
+
57
+ # sinatra configuration
58
+ configure do
59
+ set :root, File.dirname(__FILE__)
60
+ set :bind, config[:bind_ip]
61
+ set :port, config[:port]
62
+ set :server, %w[thin mongrel webrick]
63
+ set :show_exceptions, true
64
+ end
65
+
66
+ before do
67
+ content_type :json
68
+ end
69
+
70
+ not_found do
71
+ content_type :html
72
+ @status = status.to_i
73
+ erb :help
74
+ end
75
+
76
+ helpers do
77
+ end
78
+
79
+ error do
80
+ 'Sorry there was a nasty error - ' + env['sinatra.error'].name
81
+ end
82
+
83
+ ['/', '/help', '/usage'].each do |route|
84
+ get route do
85
+ content_type :html
86
+ erb :help
87
+ end
88
+ end
89
+
90
+ # display the varnish banner containing varnish version information
91
+ get '/banner' do
92
+ varnish.banner
93
+ end
94
+
95
+ # run varnishadm ping call to varnish
96
+ get '/ping' do
97
+ varnish.ping
98
+ end
99
+
100
+ # report the status of the varnish process
101
+ get '/status' do
102
+ varnish.status
103
+ end
104
+
105
+ # display all backends and state
106
+ get '/list' do
107
+ varnish.list_backends(:json => true)
108
+ end
109
+
110
+ # purge cache objects using the ban feature
111
+ get '/ban' do
112
+ varnish.ban_all
113
+ end
114
+
115
+ # set the health of a backend. Acceptable actions are "sick" and "auto". Auto indicates the varnish probe should decide whether to send traffic to this backend based on probe health
116
+ # only one backend at a time can be changed. This is a safety feature due to varnish-cli greedy and unpredictable expression pattern matching.
117
+ get %r{^/(.*?)/(in|out)$} do
118
+ backend = params[:captures].first
119
+ action = params[:captures].last
120
+ health = action == 'out' ? 'sick' : 'auto'
121
+ backends = varnish.set_health(backend,health)
122
+
123
+ if backends.empty?
124
+ content_type :html
125
+ halt 400, erb(:error, :locals => { :message => "No backend found for pattern #{backend}"})
126
+ elsif backends.class == Hash && backends.has_key?("error")
127
+ content_type :html
128
+ error = backends['error']
129
+ halt 400, erb(:error, :locals => { :message => error})
130
+ end
131
+ redirect to('/list')
132
+ end
133
+
134
+ =begin
135
+ v = Varnish.new
136
+ puts v.status
137
+ puts "="
138
+ puts v.banner
139
+ puts "="
140
+ puts v.list_backends(:expression => "server3", :json=>true)
141
+ puts "="
142
+ puts v.list_backends(:expression => "server2",:json=>true)
143
+ puts v.set_health("server11","sick")
144
+ puts v.set_health("server3","auto")
145
+ puts v.set_health("server","auto",false)
146
+ puts "="
147
+ puts v.ping
148
+ puts "="
149
+ puts v.ban_all
150
+ =end
151
+ run! if app_file == $0
152
+ end
@@ -0,0 +1,11 @@
1
+ ---
2
+ port: 10001
3
+ bind_ip: '0.0.0.0'
4
+ secret: /home/vagrant/secret
5
+ mgmt_port: 6082
6
+ mgmt_host: localhost
7
+ varnishadm_path: /usr/bin/varnishadm
8
+ instance: default
9
+ use_zookeeper: false
10
+ zookeeper_host: autodeploy38-2:2181
11
+ zookeeper_basenode: /varnish
@@ -0,0 +1,9 @@
1
+ <html>
2
+ <style>
3
+ h2 {
4
+ text-align: center;
5
+ color: red;
6
+ }
7
+ </style>
8
+ <h2><%= message %></h2>
9
+ </html>
@@ -0,0 +1,91 @@
1
+ <html>
2
+ <style>
3
+ h2 {
4
+ text-align: center;
5
+ color: red;
6
+ }
7
+ h1 {
8
+ text-align: left;
9
+ }
10
+ table {
11
+ border-spacing: 5px;
12
+ }
13
+ tr:nth-child(even) {
14
+ background-color: #eee;
15
+ }
16
+ tr:nth-child(odd) {
17
+ background-color: #fff;
18
+ }
19
+ th {
20
+ text-align: left;
21
+ color: white;
22
+ background-color: black;
23
+ }
24
+ </style>
25
+ <% if status == 404 %>
26
+ <h2>Error: <%= request.path_info %> is not a valid url</h2>
27
+ <% end %>
28
+
29
+
30
+
31
+ <table>
32
+ <caption><h3>Varnish REST API help</h3></caption>
33
+ <tr>
34
+ <th>Method</th>
35
+ <th>URL</th>
36
+ <th>Description</th>
37
+ <th>Remarks</th>
38
+ </tr>
39
+
40
+ <tr>
41
+ <td>GET</td>
42
+ <td>/list</td>
43
+ <td>list all backends</td>
44
+ <td>read-only</td>
45
+ </tr>
46
+
47
+ <tr>
48
+ <td>GET</td>
49
+ <td>/ping</td>
50
+ <td>ping varnish process</td>
51
+ <td>read-only</td>
52
+ </tr>
53
+ <tr>
54
+ <td>GET</td>
55
+ <td>/banner</td>
56
+ <td>display varnish banner with version information</td>
57
+ <td>read-only</td>
58
+ </tr>
59
+
60
+ <tr>
61
+ <td>GET</td>
62
+ <td>/status</td>
63
+ <td>display status of varnish process</td>
64
+ <td>read-only</td>
65
+ </tr>
66
+
67
+ <tr>
68
+ <td>GET</td>
69
+ <td>/ban</td>
70
+ <td>ban all objects immediately</td>
71
+ <td>effectively purges objects. See <a href="https://www.varnish-cache.org/docs/3.0/tutorial/purging.html">here</a> and <a href="https://www.varnish-software.com/static/book/Cache_invalidation.html">here</a></td>
72
+ </tr>
73
+
74
+ <tr>
75
+ <td>GET</td>
76
+ <td>/{backend}/in</td>
77
+ <td>sets backend health to "auto", allowing probe to decide if backend is healthy</td>
78
+ <td>use partial or complete backend name as it appears in VCL. The Rest API will not process request if more than one backend is found matching for the pattern</td>
79
+ </tr>
80
+ <tr>
81
+ <td>GET</td>
82
+ <td>/{backend}/out</td>
83
+ <td>sets backend health to "sick"</td>
84
+ <td>use partial or complete backend name as it appears in VCL. The Rest API will not process request if more than one backend is found matching for the pattern</td>
85
+ </tr>
86
+ <tr>
87
+ </tr>
88
+ </table>
89
+
90
+
91
+ </html>
@@ -0,0 +1,30 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'varnish_rest_api/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "varnish_rest_api"
8
+ spec.version = VarnishRestApi::VERSION
9
+ spec.authors = ["Jonathan Colby"]
10
+ spec.email = ["jcolby@team.mobile.de"]
11
+ spec.summary = %q{A sinatra rest api for varnish.}
12
+ spec.description = %q{A restful http api for setting backend health, banning cache objects and getting status information. Executes varnishadm via http rest calls.}
13
+ spec.homepage = "http://rubygems.org/gems/varnish_rest_api"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.files << ["bin/varnishrestapi.rb"]
18
+ spec.files << ["examples/config.ru"]
19
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
20
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
21
+ spec.require_paths = ["lib"]
22
+
23
+ spec.add_dependency "sinatra"
24
+ spec.add_dependency "zk"
25
+ spec.add_dependency "zookeeper"
26
+ spec.add_dependency "json"
27
+
28
+ spec.add_development_dependency "bundler", "~> 1.7"
29
+ spec.add_development_dependency "rake", "~> 10.0"
30
+ end
metadata ADDED
@@ -0,0 +1,147 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: varnish_rest_api
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Jonathan Colby
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-03-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: sinatra
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: zk
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: zookeeper
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: json
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: bundler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '1.7'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '1.7'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rake
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '10.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '10.0'
97
+ description: A restful http api for setting backend health, banning cache objects
98
+ and getting status information. Executes varnishadm via http rest calls.
99
+ email:
100
+ - jcolby@team.mobile.de
101
+ executables:
102
+ - varnishrestapi.rb
103
+ extensions: []
104
+ extra_rdoc_files: []
105
+ files:
106
+ - ".buildpath"
107
+ - ".gitignore"
108
+ - Gemfile
109
+ - Gemfile.orig
110
+ - LICENSE.txt
111
+ - README.md
112
+ - Rakefile
113
+ - bin/varnishrestapi.rb
114
+ - examples/config.ru
115
+ - lib/varnish_rest_api.rb
116
+ - lib/varnish_rest_api.yaml
117
+ - lib/varnish_rest_api/varnish_base.rb
118
+ - lib/varnish_rest_api/version.rb
119
+ - lib/views/error.erb
120
+ - lib/views/help.erb
121
+ - varnish_rest_api.gemspec
122
+ homepage: http://rubygems.org/gems/varnish_rest_api
123
+ licenses:
124
+ - MIT
125
+ metadata: {}
126
+ post_install_message:
127
+ rdoc_options: []
128
+ require_paths:
129
+ - lib
130
+ required_ruby_version: !ruby/object:Gem::Requirement
131
+ requirements:
132
+ - - ">="
133
+ - !ruby/object:Gem::Version
134
+ version: '0'
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ version: '0'
140
+ requirements: []
141
+ rubyforge_project:
142
+ rubygems_version: 2.4.5
143
+ signing_key:
144
+ specification_version: 4
145
+ summary: A sinatra rest api for varnish.
146
+ test_files: []
147
+ has_rdoc: