From 432baee5277ecce524e2402084fe0d376eec3664 Mon Sep 17 00:00:00 2001 From: Tristan Havelick Date: Wed, 10 Feb 2016 15:34:18 -0700 Subject: [PATCH 1/5] Purge the cache only once per deployment Before, the cloudflare:cache:purge task would run once for each of the servers configured, across all roles. Really, this only needs to happen once per deploy, so now we call the CF API only once, from the local deployment machine --- capistrano-cloudflare.gemspec | 4 ++-- lib/capistrano/cloudflare/version.rb | 2 +- lib/capistrano/tasks/cloudflare.rake | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/capistrano-cloudflare.gemspec b/capistrano-cloudflare.gemspec index f3822a5..500000a 100644 --- a/capistrano-cloudflare.gemspec +++ b/capistrano-cloudflare.gemspec @@ -2,8 +2,8 @@ require File.expand_path('../lib/capistrano/cloudflare/version', __FILE__) Gem::Specification.new do |gem| - gem.authors = ["Nathan L Smith"] - gem.email = ["nlloyds@gmail.com"] + gem.authors = ["Nathan L Smith", "Tristan D Havelick"] + gem.email = ["nlloyds@gmail.com", "tristan@havelick.com"] gem.description = %q{Capistrano extensions for CloudFlare} gem.summary = %q{Lets you make CloudFlare API calls when deploying with Capistrano.} gem.homepage = "https://github.com/cramerdev/capistrano-cloudflare" diff --git a/lib/capistrano/cloudflare/version.rb b/lib/capistrano/cloudflare/version.rb index 320e021..f12e1f8 100644 --- a/lib/capistrano/cloudflare/version.rb +++ b/lib/capistrano/cloudflare/version.rb @@ -1,5 +1,5 @@ module Capistrano module CloudFlare - VERSION = '1.0.0' + VERSION = '1.0.1' end end diff --git a/lib/capistrano/tasks/cloudflare.rake b/lib/capistrano/tasks/cloudflare.rake index 8df7628..a2b27d6 100644 --- a/lib/capistrano/tasks/cloudflare.rake +++ b/lib/capistrano/tasks/cloudflare.rake @@ -2,7 +2,7 @@ namespace :cloudflare do namespace :cache do desc "Purge the CloudFlare cache" task :purge do - on roles(:all) do + run_locally do raise 'Missing CloudFlare configuration.' unless fetch(:cloudflare_options).respond_to?(:[]) response = Capistrano::CloudFlare.send_request(fetch(:cloudflare_options)) if response['result'] == 'success' From fed088036cf571be8c06f7ae1470d59992ddb06a Mon Sep 17 00:00:00 2001 From: Tristan Havelick Date: Thu, 11 Feb 2016 12:12:02 -0700 Subject: [PATCH 2/5] #7 Require at least ruby version 2.0.0 Ruby 1.9.3 was EOL'd Feburary 23 2015. It is also no longer supported by the latest version of capistrano itself, so support is being removed here. Updated the gemspec so that it's clear on RubyGems which version is required. --- .travis.yml | 1 - capistrano-cloudflare.gemspec | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 618ed7b..6b00267 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,6 +1,5 @@ language: ruby rvm: - - 1.9.3 - 2.0.0 - 2.1.0 - 2.1.1 diff --git a/capistrano-cloudflare.gemspec b/capistrano-cloudflare.gemspec index f3822a5..f18da46 100644 --- a/capistrano-cloudflare.gemspec +++ b/capistrano-cloudflare.gemspec @@ -14,6 +14,7 @@ Gem::Specification.new do |gem| gem.name = "capistrano-cloudflare" gem.require_paths = ["lib"] gem.version = Capistrano::CloudFlare::VERSION + gem.required_ruby_version = '>= 2.0.0' gem.add_dependency 'capistrano', '>= 2.0' gem.add_dependency 'json' From e9d95bf7f8c44e906638015fe85f8b0d8971c9c7 Mon Sep 17 00:00:00 2001 From: Tristan Havelick Date: Wed, 5 Oct 2016 07:46:38 -0600 Subject: [PATCH 3/5] Move to ClouldFlare API version 4 Since version 1 will be EOL'd soon --- README.md | 8 +++++--- lib/capistrano/cloudflare.rb | 16 ++++++++-------- lib/capistrano/cloudflare/version.rb | 2 +- lib/capistrano/tasks/cloudflare.rake | 2 +- spec/capistrano/cloudflare_spec.rb | 4 ++-- 5 files changed, 17 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 30e6f52..50a14bc 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,9 @@ [CloudFlare](http://www.cloudflare.com/) is a service that protects and speeds up websites. Capistrano Cloudflare provides [Capistrano](https://github.com/capistrano/capistrano/wiki/Documentation-v2.x) tasks to update your CloudFlare settings. -Capistrano CloudFlare Version 1.0 and above supports the new Capistrano v3 API. For compatbility with Capistrano v2, please use version `0.0.2`. +Capistrano CloudFlare Version 2.0 and above supports the new Capistrano v3 API. For compatbility with Capistrano v2, please use version `0.0.2`. + +This fork of the library supports CloudFlare's version 4 API Currently only cache purging is supported. @@ -27,12 +29,12 @@ When using Capistrano, add: require 'capistrano/cloudflare' set :cloudflare_options, { - :domain => 'example.com', + :zone => 'AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA', :email => 'me@example.com', :api_key => 'FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF' } -to config/deploy.rb. These options can be found in your [CloudFlare account seetings](https://www.cloudflare.com/my-account). +to config/deploy.rb. Your api key can be found in your [CloudFlare account seetings](https://www.cloudflare.com/my-account). Your Zone can be determined by called the CloudFlare API [List Zones Endpoint](https://api.cloudflare.com/#zone-list-zones) The following Capistrano tasks should now be available: diff --git a/lib/capistrano/cloudflare.rb b/lib/capistrano/cloudflare.rb index d2434e8..4e4c579 100644 --- a/lib/capistrano/cloudflare.rb +++ b/lib/capistrano/cloudflare.rb @@ -7,17 +7,17 @@ module Capistrano module CloudFlare def self.send_request(options = {}) - uri = URI('https://www.cloudflare.com/api_json.html') + zone = options[:zone] + uri = URI("https://api.cloudflare.com/client/v4/zones/#{zone}/purge_cache") http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true - request = Net::HTTP::Post.new(uri.request_uri) - request.set_form_data({ - :v => 1, - :a => 'fpurge_ts', - :z => options[:domain], - :tkn => options[:api_key], - :email => options[:email] + request = Net::HTTP::Delete.new(uri.request_uri) + request['X-Auth-Email'] = options[:email] + request['X-Auth-Key'] = options[:api_key] + + request.set_form_data({ + :purge_everything => true, }) response = JSON.parse(http.request(request).body) end diff --git a/lib/capistrano/cloudflare/version.rb b/lib/capistrano/cloudflare/version.rb index f12e1f8..9c42a6c 100644 --- a/lib/capistrano/cloudflare/version.rb +++ b/lib/capistrano/cloudflare/version.rb @@ -1,5 +1,5 @@ module Capistrano module CloudFlare - VERSION = '1.0.1' + VERSION = '2.0' end end diff --git a/lib/capistrano/tasks/cloudflare.rake b/lib/capistrano/tasks/cloudflare.rake index a2b27d6..11b1a03 100644 --- a/lib/capistrano/tasks/cloudflare.rake +++ b/lib/capistrano/tasks/cloudflare.rake @@ -6,7 +6,7 @@ namespace :cloudflare do raise 'Missing CloudFlare configuration.' unless fetch(:cloudflare_options).respond_to?(:[]) response = Capistrano::CloudFlare.send_request(fetch(:cloudflare_options)) if response['result'] == 'success' - info "Purged CloudFlare cache for #{fetch(:cloudflare_options)[:domain]}" + info "Purged CloudFlare cache for #{fetch(:cloudflare_options)[:zone]}" else error "CloudFlare cache purge failed. Reason: #{response['msg'] || 'unknown.'}" end diff --git a/spec/capistrano/cloudflare_spec.rb b/spec/capistrano/cloudflare_spec.rb index 442c152..2b418fc 100644 --- a/spec/capistrano/cloudflare_spec.rb +++ b/spec/capistrano/cloudflare_spec.rb @@ -6,13 +6,13 @@ describe '.send_request' do it 'should POST to the cloudflare API and return the response body as a hash' do options = { - domain: 'example.com', + zone: 'Z', email: 'me@example.com', api_key: 'F' } body = { 'result' => 'success' } - stub_request(:post, 'https://www.cloudflare.com/api_json.html').to_return( + stub_request(:delete, "https://api.cloudflare.com/client/v4/zones/Z/purge_cache").to_return( :status => 200, :body => body.to_json ) From 68f74a9a8cc31b125638c9122ccb552ce1b3bd18 Mon Sep 17 00:00:00 2001 From: Tristan Havelick Date: Wed, 5 Oct 2016 12:23:59 -0600 Subject: [PATCH 4/5] Made cache purge actually work with v4 api * Switched to httparty because I couldn't set the content-type header and send request params on a delete request with Net::HtTP * Fixed sucess and failure detection in rake task * Updated test to reflect actual response from cloudflare --- capistrano-cloudflare.gemspec | 1 + lib/capistrano/cloudflare.rb | 26 +++++++++++++++----------- lib/capistrano/tasks/cloudflare.rake | 4 ++-- spec/capistrano/cloudflare_spec.rb | 6 +++--- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/capistrano-cloudflare.gemspec b/capistrano-cloudflare.gemspec index 4cbd84b..65c1061 100644 --- a/capistrano-cloudflare.gemspec +++ b/capistrano-cloudflare.gemspec @@ -18,6 +18,7 @@ Gem::Specification.new do |gem| gem.add_dependency 'capistrano', '>= 2.0' gem.add_dependency 'json' + gem.add_dependency 'httparty' gem.add_development_dependency 'rake' gem.add_development_dependency 'rspec' diff --git a/lib/capistrano/cloudflare.rb b/lib/capistrano/cloudflare.rb index 4e4c579..cc0769a 100644 --- a/lib/capistrano/cloudflare.rb +++ b/lib/capistrano/cloudflare.rb @@ -1,25 +1,29 @@ require 'capistrano' require 'capistrano/cloudflare/version' require 'json' -require 'net/http' +require 'httparty' require 'rake' module Capistrano module CloudFlare def self.send_request(options = {}) zone = options[:zone] - uri = URI("https://api.cloudflare.com/client/v4/zones/#{zone}/purge_cache") - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = true - request = Net::HTTP::Delete.new(uri.request_uri) - request['X-Auth-Email'] = options[:email] - request['X-Auth-Key'] = options[:api_key] + params = { + :purge_everything => true, + } + headers = { + 'Content-Type' => 'application/json', + 'X-Auth-Email' => options[:email], + 'X-Auth-Key' => options[:api_key] + } + resp = HTTParty.delete( + "https://api.cloudflare.com/client/v4/zones/#{zone}/purge_cache", + :body => params.to_json, + :headers => headers + ) - request.set_form_data({ - :purge_everything => true, - }) - response = JSON.parse(http.request(request).body) + JSON.parse(resp.body) end end end diff --git a/lib/capistrano/tasks/cloudflare.rake b/lib/capistrano/tasks/cloudflare.rake index 11b1a03..15c2ee3 100644 --- a/lib/capistrano/tasks/cloudflare.rake +++ b/lib/capistrano/tasks/cloudflare.rake @@ -5,10 +5,10 @@ namespace :cloudflare do run_locally do raise 'Missing CloudFlare configuration.' unless fetch(:cloudflare_options).respond_to?(:[]) response = Capistrano::CloudFlare.send_request(fetch(:cloudflare_options)) - if response['result'] == 'success' + if response['result']['success'] info "Purged CloudFlare cache for #{fetch(:cloudflare_options)[:zone]}" else - error "CloudFlare cache purge failed. Reason: #{response['msg'] || 'unknown.'}" + error "CloudFlare cache purge failed. Reason: #{response['errors'].first['message'] || 'unknown.'}" end end end diff --git a/spec/capistrano/cloudflare_spec.rb b/spec/capistrano/cloudflare_spec.rb index 2b418fc..0273a3f 100644 --- a/spec/capistrano/cloudflare_spec.rb +++ b/spec/capistrano/cloudflare_spec.rb @@ -4,19 +4,19 @@ it { should be_a Module } describe '.send_request' do - it 'should POST to the cloudflare API and return the response body as a hash' do + it 'should call out to the cloudflare API and return the response body as a hash' do options = { zone: 'Z', email: 'me@example.com', api_key: 'F' } - body = { 'result' => 'success' } + body = { 'success' => true } stub_request(:delete, "https://api.cloudflare.com/client/v4/zones/Z/purge_cache").to_return( :status => 200, :body => body.to_json ) - Capistrano::CloudFlare.send_request(options).should eq(body) + Capistrano::CloudFlare.send_request(options)['success'].should eq(true) end end end From d242dec0fa64df88c0ccab49ddafc3bba1713ac6 Mon Sep 17 00:00:00 2001 From: Tristan Havelick Date: Thu, 6 Oct 2016 08:32:04 -0600 Subject: [PATCH 5/5] Check response properly for cache purge status --- lib/capistrano/tasks/cloudflare.rake | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/capistrano/tasks/cloudflare.rake b/lib/capistrano/tasks/cloudflare.rake index 15c2ee3..42a48c9 100644 --- a/lib/capistrano/tasks/cloudflare.rake +++ b/lib/capistrano/tasks/cloudflare.rake @@ -5,7 +5,7 @@ namespace :cloudflare do run_locally do raise 'Missing CloudFlare configuration.' unless fetch(:cloudflare_options).respond_to?(:[]) response = Capistrano::CloudFlare.send_request(fetch(:cloudflare_options)) - if response['result']['success'] + if response['success'] info "Purged CloudFlare cache for #{fetch(:cloudflare_options)[:zone]}" else error "CloudFlare cache purge failed. Reason: #{response['errors'].first['message'] || 'unknown.'}"