ipecache 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,3 @@
1
+ ## 0.0.1 (March 20, 2013)
2
+
3
+ Initial version.
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source :rubygems
2
+
3
+ gemspec
@@ -0,0 +1,47 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ ipecache (0.0.1)
5
+ app_conf (>= 0.4.0)
6
+ choice (>= 0.1.6)
7
+ faraday_middleware (>= 0.9.0)
8
+ savon (>= 2.1.0)
9
+
10
+ GEM
11
+ remote: http://rubygems.org/
12
+ specs:
13
+ akami (1.2.0)
14
+ gyoku (>= 0.4.0)
15
+ nokogiri (>= 1.4.0)
16
+ app_conf (0.4.0)
17
+ builder (3.0.0)
18
+ choice (0.1.6)
19
+ faraday (0.8.6)
20
+ multipart-post (~> 1.1)
21
+ faraday_middleware (0.9.0)
22
+ faraday (>= 0.7.4, < 0.9)
23
+ gyoku (1.0.0)
24
+ builder (>= 2.1.2)
25
+ httpi (2.0.2)
26
+ rack
27
+ multipart-post (1.2.0)
28
+ nokogiri (1.5.6)
29
+ nori (2.0.4)
30
+ rack (1.4.1)
31
+ savon (2.1.0)
32
+ akami (~> 1.2.0)
33
+ builder (>= 2.1.2)
34
+ gyoku (~> 1.0.0)
35
+ httpi (~> 2.0.2)
36
+ nokogiri (>= 1.4.0)
37
+ nori (~> 2.0.3)
38
+ wasabi (~> 3.0.0)
39
+ wasabi (3.0.0)
40
+ httpi (~> 2.0)
41
+ nokogiri (>= 1.4.0)
42
+
43
+ PLATFORMS
44
+ ruby
45
+
46
+ DEPENDENCIES
47
+ ipecache!
data/LICENSE ADDED
@@ -0,0 +1,13 @@
1
+ Ipecache
2
+ ----------
3
+ Author:: Jon Cowie (<jcowie@etsy.com>)
4
+ Copyright:: Copyright (c) 2013 Jon Cowie
5
+ License:: GPL
6
+
7
+ Plugin API
8
+ ----------
9
+ Modified version of code added to knife-spork under the following license:
10
+
11
+ Author:: Seth Vargo (<svargo@customink.com>)
12
+ Copyright:: Copyright (c) 2012 Seth Vargo
13
+ License:: GPL
@@ -0,0 +1,180 @@
1
+ Ipecache
2
+ ===========
3
+ Ipecache is an extensible tool for purging URLs from Caches and CDNs.
4
+
5
+ Installation
6
+ ------------
7
+ ### Gem Install (recommended)
8
+ `ipecache` is available on rubygems. Add the following to your `Gemfile`:
9
+
10
+ ```ruby
11
+ gem 'ipecache'
12
+ ```
13
+
14
+ or install the gem manually:
15
+
16
+ ```bash
17
+ gem install ipecache
18
+ ```
19
+
20
+ Ipecache Configuration
21
+ -------------------
22
+ Ipecache will not work with no configuration, so before you can purge anything, you'll need to specify some configuration for the plugins you wish to use.
23
+
24
+ Ipecache will look for a configuration file in the following locations, in ascending order of precedence:
25
+
26
+ - `/etc/ipecache-config.yml`
27
+ - `~/.ipecache/ipecache-config.yml`
28
+
29
+ Anything set in the configuration file in your home directory for example, will override options set in `/etc`.
30
+
31
+ Below is a sample config file with all supported options and all shipped plugins enabled below, followed by an explanation of each section.
32
+
33
+ Please note, if you do not want to use a particular plugin, don't specify any configuration for it and it will automatically be disabled.
34
+
35
+ ```yaml
36
+ plugins:
37
+ atschef:
38
+ knife_config: /my/.chef/knife.rb
39
+ chef_role: ATSRole
40
+ fastly:
41
+ api_key: abc123abc123abc123abc123abc123abc123
42
+ edgecast:
43
+ account_id: 1A2B
44
+ api_key: abc123
45
+ akamai:
46
+ username: myusername
47
+ password: mypassword
48
+ ```
49
+
50
+ #### atschef
51
+ For more information on how to configure the ATS/Chef plugin, please read the [plugins/ATSChef.md](plugins/ATSChef.md) file.
52
+
53
+ #### Fastly
54
+ For more information on how to configure the Fastly CDN plugin, please read the [plugins/Fastly.md](plugins/Fastly.md) file.
55
+
56
+ #### Edgecast
57
+ For more information on how to configure the Edgecast CDN plugin, please read the [plugins/Edgecast.md](plugins/Edgecast.md) file.
58
+
59
+ #### Akamai
60
+ For more information on how to configure the Akamai plugin, please read the [plugins/Akamai.md](plugins/Akamai.md) file.
61
+
62
+
63
+
64
+ Ipecache Usage
65
+ -----------
66
+ The main component of Ipecache, and the program which initialises and calls all plugins is called `ipecache`.
67
+
68
+ #### Usage
69
+ ```bash
70
+ ipecache [-f -u -c -p --status]
71
+ ```
72
+
73
+ * Mandatory Parameters (you must specify one or the other)
74
+ * -f: Specifies a file containg a newline seperated list of URLS to purge
75
+ * -u: Specifies a single URL to purge
76
+
77
+ * Optional Parameters:
78
+ * --status: Prints the status of all ipecache plugins
79
+ * -c: Indicates that only CDN plugins should be run
80
+ * -p: Indicates that only local proxy plugins should be run.
81
+
82
+
83
+ #### Example (Checking plugin status)
84
+
85
+ ```text
86
+ $> ipecache --status
87
+ Ipecache Status:
88
+
89
+ Ipecache::Plugins::Akamai: enabled
90
+ Ipecache::Plugins::ATSChef: enabled
91
+ Ipecache::Plugins::Edgecast: enabled
92
+ Ipecache::Plugins::Fastly: enabled
93
+ ```
94
+
95
+ #### Example (Purging a single URL from local proxies only)
96
+
97
+ ```text
98
+ $> ipecache -u https://img3.etsystatic.com/000/0/5241384/il_340x270.220445599.jpg -p
99
+
100
+ Running plugins registered for Proxy Purge...
101
+
102
+
103
+ Ipecache::Plugins::ATSChef: Beginning URL Purge from ATS...
104
+ Ipecache::Plugins::ATSChef: Finding ATS Servers...
105
+ Ipecache::Plugins::ATSChef: Purging https://img.mydomain.com/image9.jpg
106
+ Ipecache::Plugins::ATSChef: --Purge from cache1.mydomain.com not needed, asset not found
107
+ Ipecache::Plugins::ATSChef: --Purged from cache2.mydomain.com sucessfully
108
+
109
+ All done!
110
+ ```
111
+
112
+ #### Example (Purging a file containing 2 URLs from CDNS only)
113
+
114
+ ```text
115
+ $> ipecache -f ~/urlfile -c
116
+
117
+ Running plugins registered for CDN Purge...
118
+
119
+
120
+ Ipecache::Plugins::Akamai: Beginning URL Purge from Akamai...
121
+ Ipecache::Plugins::Akamai: Purging https://img.mydomain.com/image9.jpg
122
+ Ipecache::Plugins::Akamai: Purge successful!
123
+ Ipecache::Plugins::Akamai: Purging https://img.mydomain.com/image10.jpg
124
+ Ipecache::Plugins::Akamai: Purge successful!
125
+
126
+ Ipecache::Plugins::Edgecast: Beginning URL Purge from Edgecast...
127
+ Ipecache::Plugins::Edgecast: Purging https://img.mydomain.com/image9.jpg
128
+ Ipecache::Plugins::Edgecast: Purge successful!
129
+ Ipecache::Plugins::Edgecast: Purging https://img.mydomain.com/image10.jpg
130
+ Ipecache::Plugins::Edgecast: Purge successful!
131
+
132
+ Ipecache::Plugins::Fastly: Beginning URL Purge from Fastly...
133
+ Ipecache::Plugins::Fastly: Purging https://img.mydomain.com/image9.jpg
134
+ Ipecache::Plugins::Fastly: Purge successful!
135
+ Ipecache::Plugins::Fastly: Purging https://img.mydomain.com/imag10.jpg
136
+ Ipecache::Plugins::Fastly: Purge successful!
137
+
138
+ All done!
139
+ ```
140
+
141
+ #### Example (Purging a file containing 2 URLs from proxies and CDNS)
142
+
143
+ ```text
144
+ $> ipecache -f ~/urlfile
145
+
146
+ Running plugins registered for Proxy Purge...
147
+
148
+
149
+ Ipecache::Plugins::ATSChef: Beginning URL Purge from ATS...
150
+ Ipecache::Plugins::ATSChef: Finding ATS Servers...
151
+ Ipecache::Plugins::ATSChef: Purging https://img.mydomain.com/image9.jpg
152
+ Ipecache::Plugins::ATSChef: --Purge from cache1.mydomain.com not needed, asset not found
153
+ Ipecache::Plugins::ATSChef: --Purged from cache2.mydomain.com sucessfully
154
+ Ipecache::Plugins::ATSChef: Purging https://img.mydomain.com/image10.jpg
155
+ Ipecache::Plugins::ATSChef: --Purge from cache1.mydomain.com not needed, asset not found
156
+ Ipecache::Plugins::ATSChef: --Purged from cache2.mydomain.com sucessfully
157
+
158
+ Running plugins registered for CDN Purge...
159
+
160
+
161
+ Ipecache::Plugins::Akamai: Beginning URL Purge from Akamai...
162
+ Ipecache::Plugins::Akamai: Purging https://img.mydomain.com/image9.jpg
163
+ Ipecache::Plugins::Akamai: Purge successful!
164
+ Ipecache::Plugins::Akamai: Purging https://img.mydomain.com/image10.jpg
165
+ Ipecache::Plugins::Akamai: Purge successful!
166
+
167
+ Ipecache::Plugins::Edgecast: Beginning URL Purge from Edgecast...
168
+ Ipecache::Plugins::Edgecast: Purging https://img.mydomain.com/image9.jpg
169
+ Ipecache::Plugins::Edgecast: Purge successful!
170
+ Ipecache::Plugins::Edgecast: Purging https://img.mydomain.com/image10.jpg
171
+ Ipecache::Plugins::Edgecast: Purge successful!
172
+
173
+ Ipecache::Plugins::Fastly: Beginning URL Purge from Fastly...
174
+ Ipecache::Plugins::Fastly: Purging https://img.mydomain.com/image9.jpg
175
+ Ipecache::Plugins::Fastly: Purge successful!
176
+ Ipecache::Plugins::Fastly: Purging https://img.mydomain.com/imag10.jpg
177
+ Ipecache::Plugins::Fastly: Purge successful!
178
+
179
+ All done!
180
+ ```
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env rake
2
+ require 'bundler/gem_tasks'
@@ -0,0 +1,84 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # ipecache - A command line memcached traffic analyzer
4
+ #
5
+ # Author:: Jon Cowie (<jcowie@etsy.com>)
6
+
7
+ require 'choice'
8
+ require 'ipecache/runner'
9
+ include Ipecache::Runner
10
+
11
+ Choice.options do
12
+ header ""
13
+ header "Specific options:"
14
+
15
+ option :status, :required => false do
16
+ long '--status'
17
+ desc 'Show ipecache status information'
18
+ end
19
+
20
+ option :urlfile, :required => false do
21
+ short '-f'
22
+ long '--file=PATH_TO_URL_FILE'
23
+ desc 'File containing urls to purge from caches'
24
+ end
25
+
26
+ option :url, :required => false do
27
+ short '-u'
28
+ long '--url=URL_TO_PURGE'
29
+ desc 'URL to be purged from caches'
30
+ end
31
+
32
+ option :proxyonly, :required => false do
33
+ short '-p'
34
+ long '--proxy-only'
35
+ desc 'Only purge from proxies'
36
+ end
37
+
38
+ option :cdnonly, :required => false do
39
+ short '-c'
40
+ long '--cdn-only'
41
+ desc 'Only purge from CDNs'
42
+ end
43
+ end
44
+
45
+ if Choice.choices[:status]
46
+ puts "Ipecache Status:"
47
+ puts ""
48
+ Ipecache::Plugins.klasses.each do |klass|
49
+ plugin = klass.new(:config => ipecache_config)
50
+ puts "#{klass}: #{plugin.enabled? ? 'enabled' : 'disabled'}"
51
+ end
52
+ exit 0
53
+ end
54
+
55
+ if Choice.choices[:url]
56
+ @urls = [Choice.choices[:url]]
57
+ elsif Choice.choices[:urlfile]
58
+ urlfile = Choice.choices[:urlfile]
59
+ if File.exists?(urlfile)
60
+ @urls = File.open(urlfile, 'r').readlines
61
+ else
62
+ puts "Error: #{urlfile} doesn't exist."
63
+ exit 1
64
+ end
65
+ else
66
+ Choice.help
67
+ end
68
+
69
+ if !Choice.choices[:cdnonly]
70
+ puts ""
71
+ puts "Running plugins registered for Proxy Purge..."
72
+ puts ""
73
+ run_plugins(:proxy_purge)
74
+ end
75
+
76
+ if !Choice.choices[:proxyonly]
77
+ puts ""
78
+ puts "Running plugins registered for CDN Purge..."
79
+ puts ""
80
+ run_plugins(:cdn_purge)
81
+ end
82
+
83
+ puts ""
84
+ puts "All done!"
@@ -0,0 +1,22 @@
1
+ $:.push File.expand_path('../lib', __FILE__)
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = 'ipecache'
5
+ gem.version = '0.0.1'
6
+ gem.authors = ["Jon Cowie"]
7
+ gem.email = 'jonlives@gmail.com'
8
+ gem.homepage = 'https://github.com/jonlives/ipecache'
9
+ gem.summary = "An extensible tool for purging urls from caches and CDNs"
10
+ gem.description = "An extensible tool for purging urls from caches and CDNs"
11
+
12
+ gem.files = `git ls-files`.split($\)
13
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
14
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
15
+ gem.name = "ipecache"
16
+ gem.require_paths = ["lib"]
17
+
18
+ gem.add_runtime_dependency 'app_conf', '>= 0.4.0'
19
+ gem.add_runtime_dependency 'choice', '>= 0.1.6'
20
+ gem.add_runtime_dependency 'faraday_middleware', '>= 0.9.0'
21
+ gem.add_runtime_dependency 'savon', '>= 2.1.0'
22
+ end
@@ -0,0 +1,3 @@
1
+ module Ipecache
2
+ require 'ipecache/plugins'
3
+ end
@@ -0,0 +1,22 @@
1
+ module Ipecache
2
+ module Plugins
3
+ # Load each of the drop-in plugins
4
+ Dir[File.expand_path('../plugins/**/*.rb', __FILE__)].each { |f| require f }
5
+
6
+ def self.run(options = {})
7
+ hook = options[:hook].to_sym
8
+
9
+ klasses.each do |klass|
10
+ plugin = klass.new(options)
11
+ plugin.send(hook) if plugin.respond_to?(hook) && plugin.enabled?
12
+ end
13
+ end
14
+
15
+ # Get and return a list of all subclasses (plugins) that are not the base plugin
16
+ def self.klasses
17
+ @@klasses ||= self.constants.collect do |c|
18
+ self.const_get(c) if self.const_get(c).is_a?(Class) && self.const_get(c) != Ipecache::Plugins::Plugin
19
+ end.compact
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,65 @@
1
+ require 'ipecache/plugins/plugin'
2
+
3
+ module Ipecache
4
+ module Plugins
5
+ class Akamai < Plugin
6
+ name :akamai
7
+ hooks :cdn_purge
8
+
9
+ def perform
10
+ safe_require 'savon'
11
+
12
+ username = config.username
13
+ password = config.password
14
+
15
+ if username.nil?
16
+ plugin_puts("Akamai username not specified, Exiting...")
17
+ exit 1
18
+ end
19
+
20
+ if password.nil?
21
+ plugin_puts("Akamai password key not specified, Exiting...")
22
+ exit 1
23
+ end
24
+
25
+ puts ""
26
+ plugin_puts "Beginning URL Purge from Akamai..."
27
+
28
+ urls.each do |u|
29
+ url = u.chomp
30
+ plugin_puts ("Purging #{url}")
31
+
32
+ savon_client = Savon.client({log_level: :info, log: false, convert_request_keys_to: :none, wsdl: 'https://ccuapi.akamai.com/ccuapi-axis.wsdl'})
33
+ response = savon_client.call(:purge_request, xml: "<?xml version=\"1.0\" encoding=\"UTF-8\"?>
34
+ <soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"
35
+ xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\"
36
+ xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"
37
+ soap:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\"
38
+ xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">
39
+ <soap:Body>
40
+ <purgeRequest xmlns=\"http://ccuapi.akamai.com/purge\">
41
+ <name xsi:type=\"xsd:string\">#{username}</name>
42
+ <pwd xsi:type=\"xsd:string\">#{password}</pwd>
43
+ <network xsi:type=\"xsd:string\"></network>
44
+ <opt soapenc:arrayType=\"xsd:string[2]\" xsi:type=\"soapenc:Array\">
45
+ <item xsi:type=\"xsd:string\">type=arl</item>
46
+ <item xsi:type=\"xsd:string\">action=remove</item>
47
+ </opt>'
48
+ <uri soapenc:arrayType=\"xsd:string[1]\" xsi:type=\"soapenc:Array\">
49
+ <item xsi:type=\"xsd:string\">#{url}</item>
50
+ </uri>
51
+ </purgeRequest>
52
+ </soap:Body>
53
+ </soap:Envelope>")
54
+ response_hash = response.to_hash
55
+ if response_hash[:purge_request_response][:return][:result_msg] != "Success."
56
+ plugin_puts "An Error occured: #{response_hash[:purge_request_response][:return][:result_msg]}"
57
+ exit 1
58
+ else
59
+ plugin_puts "Purge successful!"
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,61 @@
1
+ require 'ipecache/plugins/plugin'
2
+
3
+ module Ipecache
4
+ module Plugins
5
+ class ATSChef < Plugin
6
+ name :atschef
7
+ hooks :proxy_purge
8
+
9
+ def perform
10
+ safe_require 'chef'
11
+ safe_require 'uri'
12
+
13
+ knife_file = config.knife_config || ""
14
+ chef_role = config.chef_role
15
+
16
+ if knife_file.empty?
17
+ plugin_puts "No knife config file specified. Exiting..."
18
+ exit 1
19
+ elsif File.exists?(knife_file)
20
+ Chef::Config.from_file(knife_file)
21
+ rest_api = Chef::REST.new(Chef::Config[:chef_server_url])
22
+ else
23
+ plugin_puts "Knife config file #{knife_file} doesn't exist."
24
+ exit 1
25
+ end
26
+
27
+ if !chef_role
28
+ plugin_puts "Chef role not specified, Exiting..."
29
+ exit 1
30
+ end
31
+
32
+ puts ""
33
+ plugin_puts "Beginning URL Purge from ATS..."
34
+ plugin_puts "Finding ATS Servers..."
35
+ nodes_ats_fqdns = []
36
+ nodes_ats = rest_api.get_rest("/search/node?q=role:#{chef_role}" )
37
+ nodes_ats["rows"].each do |n|
38
+ nodes_ats_fqdns << n.fqdn unless n.nil?
39
+ end
40
+
41
+ urls.each do |u|
42
+ url = u.chomp
43
+ plugin_puts ("Purging #{url}")
44
+ nodes_ats_fqdns.each do |ats|
45
+ hostname = URI.parse(url).host
46
+ path = URI.parse(url).path
47
+ result = `ssh #{ats} 'curl -X PURGE -s -o /dev/null -w \"%{http_code}\" --header \"Host: #{hostname}\" \"http://localhost#{path}\"'`
48
+ if result.include?("200")
49
+ plugin_puts "--Purged from #{ats} sucessfully"
50
+ elsif result.include?("404")
51
+ plugin_puts "--Purge from #{ats} not needed, asset not found"
52
+ else
53
+ plugin_puts "--Purge from #{ats} failed"
54
+ end
55
+
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,59 @@
1
+ require 'ipecache/plugins/plugin'
2
+
3
+ module Ipecache
4
+ module Plugins
5
+ class Edgecast < Plugin
6
+ name :edgecast
7
+ hooks :cdn_purge
8
+
9
+ def perform
10
+ safe_require 'uri'
11
+ safe_require 'faraday_middleware'
12
+ safe_require 'json'
13
+
14
+ account_id = config.account_id
15
+ api_key = config.api_key
16
+
17
+ if account_id.nil?
18
+ plugin_puts("Edgecast account id not specified, Exiting...")
19
+ exit 1
20
+ end
21
+
22
+ if api_key.nil?
23
+ plugin_puts("Edgecast API key not specified, Exiting...")
24
+ exit 1
25
+ end
26
+
27
+ puts ""
28
+ plugin_puts "Beginning URL Purge from Edgecast..."
29
+
30
+ urls.each do |u|
31
+ url = u.chomp
32
+ plugin_puts ("Purging #{url}")
33
+
34
+ connection = Faraday::Connection.new(
35
+ {:url => "https://api.edgecast.com",
36
+ :headers => { :accept => 'application/json',
37
+ :content_type => 'application/json',
38
+ :user_agent => 'Ipecache',
39
+ :authorization => "TOK:#{api_key}"},
40
+ :ssl => { :verify => true }
41
+ }) do |builder|
42
+ builder.request :json
43
+ builder.adapter Faraday.default_adapter
44
+ end
45
+
46
+ response = connection.put("/v2/mcc/customers/#{account_id}/edge/purge",{ :MediaPath => url, :MediaType => 8})
47
+
48
+ if response.status != 200
49
+ plugin_puts "Response Code: #{response.status}"
50
+ plugin_puts response.body
51
+ exit 1
52
+ else
53
+ plugin_puts "Purge successful!"
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,60 @@
1
+ require 'ipecache/plugins/plugin'
2
+ require 'net/http'
3
+
4
+ module Ipecache
5
+ module Plugins
6
+ class Fastly < Plugin
7
+ name :fastly
8
+ hooks :cdn_purge
9
+
10
+ def perform
11
+ safe_require 'uri'
12
+
13
+ api_key = config.api_key
14
+
15
+ if api_key.nil?
16
+ plugin_puts("Fastly API key not specified, Exiting...")
17
+ exit 1
18
+ end
19
+
20
+ puts ""
21
+ plugin_puts "Beginning URL Purge from Fastly..."
22
+
23
+ urls.each do |u|
24
+ url = u.chomp
25
+ plugin_puts ("Purging #{url}")
26
+ hostname = URI.parse(url).host
27
+ path = URI.parse(url).path
28
+
29
+ http = Net::HTTP.new("api.fastly.com", "443")
30
+ http.use_ssl = true
31
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
32
+
33
+ request = Net::HTTP::Purge.new(path)
34
+ request.add_field("X-Forwarded-For", "0.0.0.0")
35
+ request.add_field("Accept", "application/json")
36
+ request.add_field("User-Agent", "Ipecache")
37
+ request.add_field("Content-Type", "application/x-www-form-urlencoded")
38
+ request.add_field("X-Fastly-Key", api_key)
39
+ request.add_field("Host", hostname)
40
+
41
+ response = http.request(request)
42
+
43
+ if response.code.to_i != 200
44
+ plugin_puts "Response Code: #{response.code}"
45
+ plugin_puts response.body
46
+ exit 1
47
+ else
48
+ plugin_puts "Purge successful!"
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+
56
+ class Net::HTTP::Purge < Net::HTTPRequest
57
+ METHOD = 'PURGE'
58
+ REQUEST_HAS_BODY = false
59
+ RESPONSE_HAS_BODY = true
60
+ end
@@ -0,0 +1,66 @@
1
+ module Ipecache
2
+ module Plugins
3
+ class Plugin
4
+ # This is the name of the plugin. It must correspond to the name in the yaml configuration
5
+ # file in order to load this plugin. If an attribute is passed in, the name is set to that
6
+ # given value. Otherwise, the name is returned.
7
+ def self.name(name = nil)
8
+ if name.nil?
9
+ class_variable_get(:@@name)
10
+ else
11
+ class_variable_set(:@@name, name)
12
+ end
13
+ end
14
+
15
+ # This is a convenience method for defining multiple hooks in a single call.
16
+ def self.hooks(*the_hooks)
17
+ [the_hooks].flatten.each{ |the_hook| hook(the_hook) }
18
+ end
19
+
20
+ # When defining a hook, we define a method on the instance that corresponds to that
21
+ # hook. That will be fired when the hook is fired.
22
+ def self.hook(the_hook)
23
+ self.send(:define_method, the_hook.to_sym) do
24
+ perform
25
+ end
26
+ end
27
+
28
+ def initialize(options = {})
29
+ @options = {
30
+ :payload => {}
31
+ }.merge(options)
32
+ end
33
+
34
+ def enabled?
35
+ !(config.nil? || config.enabled == false)
36
+ end
37
+
38
+ def urls
39
+ @options[:urls]
40
+ end
41
+
42
+ def name
43
+ self.class.to_s
44
+ end
45
+
46
+ def plugin_puts(message)
47
+ puts "#{name}: #{message}"
48
+ end
49
+
50
+ private
51
+ def config
52
+ @options[:config].plugins.send(self.class.name.to_sym) unless @options[:config].nil? || @options[:config].plugins.nil?
53
+ end
54
+
55
+ # Wrapper method around require that attempts to include the associated file. If it does not exist
56
+ # or cannot be loaded, an nice error is produced instead of blowing up.
57
+ def safe_require(file)
58
+ begin
59
+ require file
60
+ rescue LoadError
61
+ raise "You are using a plugin for ipecache that requires #{file}, but you have not installed it. Please either run \"gem install #{file}\", add #{file} to your Gemfile or remove the plugin from your configuration."
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
@@ -0,0 +1,44 @@
1
+ require 'app_conf'
2
+ require 'json'
3
+
4
+ require 'ipecache/plugins'
5
+
6
+ module Ipecache
7
+ module Runner
8
+ module ClassMethods; end
9
+
10
+ module InstanceMethods
11
+ def ipecache_config
12
+ return @ipecache_config unless @ipecache_config.nil?
13
+
14
+ @ipecache_config = AppConf.new
15
+ load_paths = [ File.expand_path('config/ipecache-config.yml'), '/etc/ipecache-config.yml', File.expand_path('~/.ipecache/ipecache-config.yml') ]
16
+ load_paths.each do |load_path|
17
+ if File.exists?(load_path)
18
+ @ipecache_config.load(load_path)
19
+ end
20
+ end
21
+
22
+ @ipecache_config
23
+ end
24
+
25
+ def run_plugins(hook)
26
+ urls = @urls
27
+ Ipecache::Plugins.run(
28
+ :config => ipecache_config,
29
+ :hook => hook.to_sym,
30
+ :urls => urls
31
+ )
32
+ end
33
+
34
+ def pretty_print_json(json)
35
+ JSON.pretty_generate(json)
36
+ end
37
+ end
38
+
39
+ def self.included(receiver)
40
+ receiver.extend(ClassMethods)
41
+ receiver.send(:include, InstanceMethods)
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,34 @@
1
+ ATSChef
2
+ ========
3
+ Queries chef for nodes in the specified role and purges the URL list from each server
4
+
5
+ Gem Requirements
6
+ ----------------
7
+ This plugin requires the following gems:
8
+
9
+ ```ruby
10
+ gem 'chef'
11
+ ```
12
+
13
+ Hooks
14
+ -----
15
+ - `proxy_purge`
16
+
17
+ Configuration
18
+ -------------
19
+ ```yaml
20
+ plugins:
21
+ atschef:
22
+ knife_config: /my/.chef/knife.rb
23
+ chef_role: ATSRole
24
+ ```
25
+
26
+ #### knife_config
27
+ This is the knife.rb that ipecache can use to search against your Chef server
28
+
29
+ - Type: `String`
30
+
31
+ #### chef_role
32
+ This is the chef role which your ATS servers live in
33
+
34
+ - Type: `String`
@@ -0,0 +1,26 @@
1
+ Akamai
2
+ ========
3
+ Purges URLS from the Akamai CDN using the Content Control Utility API
4
+
5
+ Hooks
6
+ -----
7
+ - `cdn_purge`
8
+
9
+ Configuration
10
+ -------------
11
+ ```yaml
12
+ plugins:
13
+ akamai:
14
+ username: foo
15
+ password: bar
16
+ ```
17
+
18
+ #### username
19
+ This is the username of the Akamai account you want to use
20
+
21
+ - Type: `String`
22
+
23
+ #### password
24
+ This is the username of the Akamai account you want to use
25
+
26
+ - Type: `String`
@@ -0,0 +1,26 @@
1
+ Edgecast
2
+ ========
3
+ Purges URLS from the Edgecast CDN - please note this currently only works with HTTP Small objects.
4
+
5
+ Hooks
6
+ -----
7
+ - `cdn_purge`
8
+
9
+ Configuration
10
+ -------------
11
+ ```yaml
12
+ plugins:
13
+ edgecast:
14
+ account_id: 1ABC
15
+ api_key: aaaa-aaaaaa-aaaaaa-aaaaa
16
+ ```
17
+
18
+ #### account_id
19
+ This is your Edgecast account number, found at the top of the Edgecast admin interface
20
+
21
+ - Type: `String`
22
+
23
+ #### api_key
24
+ This is your Edgecast API key
25
+
26
+ - Type: `String`
@@ -0,0 +1,20 @@
1
+ Fastly
2
+ ========
3
+ Purges URLS from the Fastly CDN
4
+
5
+ Hooks
6
+ -----
7
+ - `cdn_purge`
8
+
9
+ Configuration
10
+ -------------
11
+ ```yaml
12
+ plugins:
13
+ fastly:
14
+ api_key: ab123ab123ab123ab123ab123ab123
15
+ ```
16
+
17
+ #### api_key
18
+ This is your fastly API key
19
+
20
+ - Type: `String`
@@ -0,0 +1,63 @@
1
+ Plugins Directory
2
+ =================
3
+ This folder contains relevant documentation for each KnifeSpork plugin. For more information, usage, and options for an particular plugin, click on the assoicated markdown file in the tree above.
4
+
5
+ Creating a Plugin
6
+ -----------------
7
+ To create a plugin, start with the following basic boiler template:
8
+
9
+ ```ruby
10
+ require 'ipecache/plugins/plugin'
11
+
12
+ module Ipecache
13
+ module Plugins
14
+ class MyPlugin < Plugin
15
+ name :my_plugin
16
+ hooks :my_hooks
17
+
18
+ def perform
19
+ # your plugin code here
20
+ end
21
+ end
22
+ end
23
+ end
24
+ ```
25
+
26
+ **Don't forget to update the class name and the `name` at the very top of the class!**
27
+
28
+ Hooks
29
+ -----
30
+
31
+ Currently, the only hooks called by the ipecache binary are "proxy_purge" (for plugins for "local" proxy servers) and "cdn_purge" (for CDN plugins). These hooks determine whether or not your plugin will be called when the -c and -p options are passed to the ipecache binary.
32
+
33
+ Helpers
34
+ -------
35
+ The following "helpers" or "methods" are exposed:
36
+
37
+ #### safe_require
38
+ This method allows you to safely require a gem. This is helpful when your plugin requires an external plugin. It will output a nice error message if the gem cannot be loaded and stop executing.
39
+
40
+ #### urls
41
+ This method gives you the list of URLS to be purged
42
+
43
+ #### plugin_puts
44
+ This method prints strings prefixed by the class name of your plugin, for clarity of output
45
+
46
+ #### config
47
+ This method returns the config associated with the current plugin. For example, if a `spork-config.yml` file looked like this:
48
+
49
+ ```yaml
50
+ plugins:
51
+ my_plugin:
52
+ option_1: my_value
53
+ option_2: other_value
54
+ ```
55
+
56
+ then
57
+
58
+ ```text
59
+ config.option_1 #=> 'my_value'
60
+ config.option_2 #=> 'other_value'
61
+ ```
62
+
63
+ This uses `app_conf`, so you access the keys as methods, not `[]`.
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ipecache
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jon Cowie
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-20 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: app_conf
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: 0.4.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: 0.4.0
30
+ - !ruby/object:Gem::Dependency
31
+ name: choice
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: 0.1.6
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: 0.1.6
46
+ - !ruby/object:Gem::Dependency
47
+ name: faraday_middleware
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: 0.9.0
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: 0.9.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: savon
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: 2.1.0
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: 2.1.0
78
+ description: An extensible tool for purging urls from caches and CDNs
79
+ email: jonlives@gmail.com
80
+ executables:
81
+ - ipecache
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - CHANGELOG.md
86
+ - Gemfile
87
+ - Gemfile.lock
88
+ - LICENSE
89
+ - README.md
90
+ - Rakefile
91
+ - bin/ipecache
92
+ - ipecache.gemspec
93
+ - lib/ipecache.rb
94
+ - lib/ipecache/plugins.rb
95
+ - lib/ipecache/plugins/akamai.rb
96
+ - lib/ipecache/plugins/ats_chef.rb
97
+ - lib/ipecache/plugins/edgecast.rb
98
+ - lib/ipecache/plugins/fastly.rb
99
+ - lib/ipecache/plugins/plugin.rb
100
+ - lib/ipecache/runner.rb
101
+ - plugins/ATSChef.md
102
+ - plugins/Akamai.md
103
+ - plugins/Edgecast.md
104
+ - plugins/Fastly.md
105
+ - plugins/README.md
106
+ homepage: https://github.com/jonlives/ipecache
107
+ licenses: []
108
+ post_install_message:
109
+ rdoc_options: []
110
+ require_paths:
111
+ - lib
112
+ required_ruby_version: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ required_rubygems_version: !ruby/object:Gem::Requirement
119
+ none: false
120
+ requirements:
121
+ - - ! '>='
122
+ - !ruby/object:Gem::Version
123
+ version: '0'
124
+ requirements: []
125
+ rubyforge_project:
126
+ rubygems_version: 1.8.24
127
+ signing_key:
128
+ specification_version: 3
129
+ summary: An extensible tool for purging urls from caches and CDNs
130
+ test_files: []
131
+ has_rdoc: