ipecache 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.
@@ -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: