middleman-cdn 0.1.3 → 0.1.5
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.
- checksums.yaml +4 -4
- data/.travis.yml +1 -2
- data/Rakefile +0 -6
- data/lib/middleman-cdn/cdns/base.rb +23 -0
- data/lib/middleman-cdn/cdns/cloudflare.rb +22 -20
- data/lib/middleman-cdn/cdns/cloudfront.rb +23 -19
- data/lib/middleman-cdn/commands.rb +9 -6
- data/lib/middleman-cdn/version.rb +1 -1
- data/middleman-cdn.gemspec +3 -14
- data/spec/lib/middleman-cdn/cdns/base_protocol.rb +52 -0
- data/spec/lib/middleman-cdn/cdns/cloudflare_spec.rb +251 -0
- data/spec/lib/middleman-cdn/cdns/cloudfront_spec.rb +68 -0
- data/spec/lib/middleman-cdn/commands_spec.rb +2 -38
- metadata +14 -69
- data/Guardfile +0 -9
- data/features/support/env.rb +0 -6
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 31655005e9acd71dfa558dbb3272beb2ae09fc1a
|
|
4
|
+
data.tar.gz: 123df0647636d59cab7640582d2c06e49b043480
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 76253f654ec0e6e6656707820144472b0e14ac3e49601fd5df3efbb6d6d77a53fa09d16dfa8d32a1e66158da11df069b003646b321a2b33bf723c2d8d3c8c3f4
|
|
7
|
+
data.tar.gz: 1d9671fbe2afafddfbc3980f4aadc003691a08945c7ca7d591523d2e057ccda79bf36ea261dccb910ea53f0efaadec962b0480058e1e5481751f3cbb29f150fa
|
data/.travis.yml
CHANGED
data/Rakefile
CHANGED
|
@@ -3,12 +3,6 @@ require 'rspec/core/rake_task'
|
|
|
3
3
|
require 'bundler'
|
|
4
4
|
Bundler::GemHelper.install_tasks
|
|
5
5
|
|
|
6
|
-
require 'cucumber/rake/task'
|
|
7
|
-
|
|
8
|
-
Cucumber::Rake::Task.new(:cucumber, 'Run features that should pass') do |t|
|
|
9
|
-
t.cucumber_opts = "--color --tags ~@wip --strict --format #{ENV['CUCUMBER_FORMAT'] || 'Fivemat'}"
|
|
10
|
-
end
|
|
11
|
-
|
|
12
6
|
RSpec::Core::RakeTask.new(:spec)
|
|
13
7
|
|
|
14
8
|
task :default => :spec
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module Middleman
|
|
2
|
+
module Cli
|
|
3
|
+
|
|
4
|
+
class BaseCDN
|
|
5
|
+
def self.example_configuration
|
|
6
|
+
config_lines = self.example_configuration_elements.map do |config_key, config_info|
|
|
7
|
+
" #{config_key.to_s}: #{config_info[0]}".ljust(30) + " #{config_info[1]}"
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
<<-TEXT
|
|
11
|
+
cdn.#{self.key} = {
|
|
12
|
+
#{config_lines.join("\n")}
|
|
13
|
+
}
|
|
14
|
+
TEXT
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def say_status(status, newline: true, header: true)
|
|
18
|
+
::Middleman::Cli::CDN.say_status(self.class.key, status, newline: newline, header: header)
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
end
|
|
23
|
+
end
|
|
@@ -5,46 +5,48 @@ require "active_support/core_ext/string"
|
|
|
5
5
|
module Middleman
|
|
6
6
|
module Cli
|
|
7
7
|
|
|
8
|
-
class CloudFlareCDN
|
|
8
|
+
class CloudFlareCDN < BaseCDN
|
|
9
9
|
def self.key
|
|
10
10
|
"cloudflare"
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def self.
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
TEXT
|
|
13
|
+
def self.example_configuration_elements
|
|
14
|
+
{
|
|
15
|
+
client_api_key: ['"..."', "# default ENV['CLOUDFLARE_CLIENT_API_KEY']"],
|
|
16
|
+
email: ['"..."', "# default ENV['CLOUDFLARE_EMAIL']"],
|
|
17
|
+
zone: ['"..."', ""],
|
|
18
|
+
base_urls: [['http://example.com', 'https://example.com'], ""]
|
|
19
|
+
}
|
|
22
20
|
end
|
|
23
21
|
|
|
24
22
|
def invalidate(options, files)
|
|
25
23
|
options[:client_api_key] ||= ENV['CLOUDFLARE_CLIENT_API_KEY']
|
|
26
24
|
options[:email] ||= ENV['CLOUDFLARE_EMAIL']
|
|
25
|
+
|
|
27
26
|
[:client_api_key, :email, :zone, :base_urls].each do |key|
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
if options[key].blank?
|
|
28
|
+
say_status("Error: Configuration key cloudflare[:#{key}] is missing.".light_red)
|
|
29
|
+
raise
|
|
30
|
+
end
|
|
32
31
|
end
|
|
33
|
-
|
|
34
|
-
|
|
32
|
+
|
|
33
|
+
options[:base_urls] = [options[:base_urls]] if options[:base_urls].is_a?(String)
|
|
34
|
+
if !options[:base_urls].is_a?(Array)
|
|
35
|
+
say_status("Error: Configuration key cloudflare[:base_urls] must be an array and contain at least one base url.".light_red)
|
|
36
|
+
raise
|
|
35
37
|
end
|
|
36
38
|
|
|
39
|
+
cloudflare = ::CloudFlare::connection(options[:client_api_key], options[:email])
|
|
37
40
|
options[:base_urls].each do |base_url|
|
|
38
41
|
files.each do |file|
|
|
39
|
-
cloudflare = ::CloudFlare::connection(options[:client_api_key], options[:email])
|
|
40
42
|
begin
|
|
41
43
|
url = "#{base_url}#{file}"
|
|
42
|
-
|
|
44
|
+
say_status("Invalidating #{url}... ", newline: false)
|
|
43
45
|
cloudflare.zone_file_purge(options[:zone], "#{base_url}#{file}")
|
|
44
46
|
rescue => e
|
|
45
|
-
|
|
47
|
+
say_status(", " + "error: #{e.message}".light_red, header: false)
|
|
46
48
|
else
|
|
47
|
-
|
|
49
|
+
say_status("✔".light_green, header: false)
|
|
48
50
|
end
|
|
49
51
|
end
|
|
50
52
|
end
|
|
@@ -4,31 +4,32 @@ require "active_support/core_ext/string"
|
|
|
4
4
|
module Middleman
|
|
5
5
|
module Cli
|
|
6
6
|
|
|
7
|
-
class CloudFrontCDN
|
|
7
|
+
class CloudFrontCDN < BaseCDN
|
|
8
8
|
INVALIDATION_LIMIT = 1000
|
|
9
9
|
|
|
10
10
|
def self.key
|
|
11
11
|
"cloudfront"
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
-
def self.
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
TEXT
|
|
14
|
+
def self.example_configuration_elements
|
|
15
|
+
{
|
|
16
|
+
access_key_id: ['"..."', "# default ENV['AWS_ACCESS_KEY_ID']"],
|
|
17
|
+
secret_access_key: ['"..."', "# default ENV['AWS_SECRET_ACCESS_KEY']"],
|
|
18
|
+
distribution_id: ['"..."', ""]
|
|
19
|
+
}
|
|
22
20
|
end
|
|
23
21
|
|
|
24
22
|
def invalidate(options, files)
|
|
25
23
|
options[:access_key_id] ||= ENV['AWS_ACCESS_KEY_ID']
|
|
26
24
|
options[:secret_access_key] ||= ENV['AWS_SECRET_ACCESS_KEY']
|
|
27
25
|
[:access_key_id, :secret_access_key, :distribution_id].each do |key|
|
|
28
|
-
|
|
26
|
+
if options[key].blank?
|
|
27
|
+
say_status("Error: Configuration key cloudfront[:base_urls] is missing.".light_red)
|
|
28
|
+
raise
|
|
29
|
+
end
|
|
29
30
|
end
|
|
30
31
|
|
|
31
|
-
cloudfront = Fog::CDN.new({
|
|
32
|
+
cloudfront = ::Fog::CDN.new({
|
|
32
33
|
:provider => 'AWS',
|
|
33
34
|
:aws_access_key_id => options[:access_key_id],
|
|
34
35
|
:aws_secret_access_key => options[:secret_access_key]
|
|
@@ -37,22 +38,25 @@ TEXT
|
|
|
37
38
|
distribution = cloudfront.distributions.get(options[:distribution_id])
|
|
38
39
|
|
|
39
40
|
if files.count <= INVALIDATION_LIMIT
|
|
40
|
-
|
|
41
|
+
say_status("Invalidating #{files.count} files... ", newline: false)
|
|
41
42
|
invalidation = distribution.invalidations.create(:paths => files)
|
|
42
|
-
|
|
43
|
-
|
|
43
|
+
if invalidation.status != 'InProgress'
|
|
44
|
+
say_status("Invalidation status is #{invalidation.status}. Expected 'InProgress'.".red.bold, header: false)
|
|
45
|
+
raise
|
|
46
|
+
end
|
|
47
|
+
say_status("✔".light_green, header: false)
|
|
44
48
|
else
|
|
45
49
|
slices = files.each_slice(INVALIDATION_LIMIT)
|
|
46
|
-
|
|
50
|
+
say_status("Invalidating #{files.count} files in #{slices.count} batch(es) ")
|
|
47
51
|
slices.each_with_index do |slice, i|
|
|
48
|
-
|
|
52
|
+
say_status("Invalidating batch #{i + 1}... ", newline: false)
|
|
49
53
|
invalidation = distribution.invalidations.create(:paths => slice)
|
|
50
54
|
invalidation.wait_for { ready? } unless i == slices.count - 1
|
|
51
|
-
|
|
55
|
+
say_status("✔".light_green, header: false)
|
|
52
56
|
end
|
|
53
57
|
end
|
|
54
|
-
|
|
55
|
-
|
|
58
|
+
say_status("It might take 10 to 15 minutes until all files are invalidated.")
|
|
59
|
+
say_status('Please check the AWS Management Console to see the status of the invalidation.')
|
|
56
60
|
end
|
|
57
61
|
end
|
|
58
62
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
require "middleman-core/cli"
|
|
2
2
|
require "middleman-cdn/extension"
|
|
3
|
+
require "middleman-cdn/cdns/base.rb"
|
|
3
4
|
require "middleman-cdn/cdns/cloudflare.rb"
|
|
4
5
|
require "middleman-cdn/cdns/cloudfront.rb"
|
|
6
|
+
require "colorize"
|
|
5
7
|
|
|
6
8
|
module Middleman
|
|
7
9
|
module Cli
|
|
@@ -33,7 +35,7 @@ module Middleman
|
|
|
33
35
|
end
|
|
34
36
|
|
|
35
37
|
files = list_files(options.filter)
|
|
36
|
-
|
|
38
|
+
self.class.say_status(nil, "Invalidating #{files.count} files with filter: " + "#{options.filter.source}".magenta.bold)
|
|
37
39
|
return if files.empty?
|
|
38
40
|
|
|
39
41
|
cdns_keyed.each do |cdn_key, cdn|
|
|
@@ -42,14 +44,15 @@ module Middleman
|
|
|
42
44
|
end
|
|
43
45
|
end
|
|
44
46
|
|
|
45
|
-
def self.say_status(status,
|
|
47
|
+
def self.say_status(cdn, status, newline: true, header: true)
|
|
46
48
|
message = ""
|
|
47
|
-
message << :cdn.to_s.rjust(12).light_green
|
|
49
|
+
message << "#{:cdn.to_s.rjust(12).light_green.bold} #{cdn.try(:yellow).try(:bold)}" if header
|
|
50
|
+
message << " " if header && cdn
|
|
48
51
|
message << status
|
|
49
|
-
if
|
|
50
|
-
print message
|
|
51
|
-
else
|
|
52
|
+
if newline
|
|
52
53
|
puts message
|
|
54
|
+
else
|
|
55
|
+
print message
|
|
53
56
|
end
|
|
54
57
|
end
|
|
55
58
|
|
data/middleman-cdn.gemspec
CHANGED
|
@@ -15,26 +15,15 @@ Gem::Specification.new do |s|
|
|
|
15
15
|
s.description = %q{Invalidate a specific set of files in your CloudFlare or CloudFront cache}
|
|
16
16
|
|
|
17
17
|
s.files = `git ls-files -z`.split("\0")
|
|
18
|
-
s.test_files = `git ls-files -z -- {fixtures,features}/*`.split("\0")
|
|
19
18
|
s.require_paths = ["lib"]
|
|
20
19
|
|
|
21
20
|
s.add_dependency 'fog', '~> 1.9'
|
|
22
21
|
s.add_dependency 'cloudflare', '~> 2.0'
|
|
23
|
-
s.add_dependency 'colorize'
|
|
22
|
+
s.add_dependency 'colorize', '~> 0.7'
|
|
23
|
+
s.add_dependency 'activesupport', '~> 4.1'
|
|
24
24
|
|
|
25
|
-
s.add_development_dependency 'cucumber', '~> 1.3'
|
|
26
|
-
s.add_development_dependency 'aruba', '~> 0.5'
|
|
27
|
-
s.add_development_dependency 'fivemat', '~> 1.3'
|
|
28
|
-
s.add_development_dependency 'simplecov', '~> 0.8'
|
|
29
25
|
s.add_development_dependency 'rake', '~> 0.9'
|
|
30
|
-
|
|
31
26
|
s.add_development_dependency 'rspec', '~> 3.0'
|
|
32
27
|
|
|
33
|
-
|
|
34
|
-
s.add_dependency 'middleman-core', '~> 3.0', '<= 3.2.0'
|
|
35
|
-
s.add_development_dependency 'activesupport', '< 4.0.0'
|
|
36
|
-
else
|
|
37
|
-
s.add_dependency 'middleman-core', '~> 3.0'
|
|
38
|
-
s.add_development_dependency 'activesupport', '~> 4.1'
|
|
39
|
-
end
|
|
28
|
+
s.add_dependency 'middleman-core', '~> 3.0'
|
|
40
29
|
end
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
shared_examples "BaseCDN" do
|
|
2
|
+
describe ".key" do
|
|
3
|
+
it "should have value" do
|
|
4
|
+
expect(described_class.key).to be_present
|
|
5
|
+
end
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
describe ".example_configuration_elements" do
|
|
9
|
+
it "should return a Hash" do
|
|
10
|
+
expect(described_class.example_configuration_elements).to be_a(Hash)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it "should return a Hash containing values that are arrays containing pairs of example values and comments" do
|
|
14
|
+
described_class.example_configuration_elements.each do |key, value|
|
|
15
|
+
expect(value).to be_a(Array)
|
|
16
|
+
expect(value.length).to eq(2)
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe ".example_configuration" do
|
|
22
|
+
before do
|
|
23
|
+
expect(described_class).to receive(:example_configuration_elements).and_return({
|
|
24
|
+
key1: ['"value"', "# comment"],
|
|
25
|
+
key2: [["arr1", "arr2"], "#"]
|
|
26
|
+
})
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
it "should output example keys containing the keys, values and comments" do
|
|
30
|
+
expect(described_class.example_configuration).to eq(
|
|
31
|
+
<<-TEXT
|
|
32
|
+
cdn.#{described_class.key} = {
|
|
33
|
+
key1: "value" # comment
|
|
34
|
+
key2: ["arr1", "arr2"] #
|
|
35
|
+
}
|
|
36
|
+
TEXT
|
|
37
|
+
)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
describe "#say_status" do
|
|
42
|
+
it "should use the Cli CDN class to say status" do
|
|
43
|
+
expect(::Middleman::Cli::CDN).to receive(:say_status).with(described_class.key, "status text", newline: false, header: false)
|
|
44
|
+
subject.say_status("status text", newline: false, header: false)
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
it "should use the Cli CDN class to say status with defaults" do
|
|
48
|
+
expect(::Middleman::Cli::CDN).to receive(:say_status).with(described_class.key, "status text", newline: true, header: true)
|
|
49
|
+
subject.say_status("status text")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
#Encoding: UTF-8
|
|
2
|
+
require 'spec_helper'
|
|
3
|
+
require 'lib/middleman-cdn/cdns/base_protocol'
|
|
4
|
+
|
|
5
|
+
describe Middleman::Cli::CloudFlareCDN do
|
|
6
|
+
it_behaves_like "BaseCDN"
|
|
7
|
+
|
|
8
|
+
describe '.key' do
|
|
9
|
+
it "should be 'cloudflare'" do
|
|
10
|
+
expect(described_class.key).to eq("cloudflare")
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe '.example_configuration_elements' do
|
|
15
|
+
it "should contain these keys" do
|
|
16
|
+
required_keys = [:client_api_key, :email, :zone, :base_urls]
|
|
17
|
+
expect(described_class.example_configuration_elements.keys).to eq(required_keys)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe '#invalidate' do
|
|
22
|
+
let(:double_cloudflare) { double("::Cloudflare") }
|
|
23
|
+
|
|
24
|
+
before do
|
|
25
|
+
allow(double_cloudflare).to receive(:zone_file_purge)
|
|
26
|
+
allow(::CloudFlare).to receive(:connection).and_return(double_cloudflare)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
let(:files) { [ "/index.html", "/", "/test/index.html", "/test/image.png" ] }
|
|
30
|
+
|
|
31
|
+
context "all options provided" do
|
|
32
|
+
let(:options) do
|
|
33
|
+
{
|
|
34
|
+
client_api_key: '000000000000000000000',
|
|
35
|
+
email: 'test@example.com',
|
|
36
|
+
zone: 'example.com',
|
|
37
|
+
base_urls: ['http://example.com', 'https://example.com']
|
|
38
|
+
}
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it "should connect to cloudflare with credentails" do
|
|
42
|
+
expect(::CloudFlare).to receive(:connection).with("000000000000000000000", "test@example.com")
|
|
43
|
+
subject.invalidate(options, files)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
it "should not raise errors" do
|
|
47
|
+
subject.invalidate(options, files)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
it "should call cloudflare to purge each file for each base url" do
|
|
51
|
+
expect(double_cloudflare).to receive(:zone_file_purge).once.ordered.with("example.com", "http://example.com/index.html")
|
|
52
|
+
expect(double_cloudflare).to receive(:zone_file_purge).once.ordered.with("example.com", "http://example.com/")
|
|
53
|
+
expect(double_cloudflare).to receive(:zone_file_purge).once.ordered.with("example.com", "http://example.com/test/index.html")
|
|
54
|
+
expect(double_cloudflare).to receive(:zone_file_purge).once.ordered.with("example.com", "http://example.com/test/image.png")
|
|
55
|
+
expect(double_cloudflare).to receive(:zone_file_purge).once.ordered.with("example.com", "https://example.com/index.html")
|
|
56
|
+
expect(double_cloudflare).to receive(:zone_file_purge).once.ordered.with("example.com", "https://example.com/")
|
|
57
|
+
expect(double_cloudflare).to receive(:zone_file_purge).once.ordered.with("example.com", "https://example.com/test/index.html")
|
|
58
|
+
expect(double_cloudflare).to receive(:zone_file_purge).once.ordered.with("example.com", "https://example.com/test/image.png")
|
|
59
|
+
subject.invalidate(options, files)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
it "should output saying invalidating each file checkmarks" do
|
|
63
|
+
files_escaped = files.map { |file| Regexp.escape(file) }
|
|
64
|
+
expect { subject.invalidate(options, files) }.to output(/#{files_escaped.join(".+")}/m).to_stdout
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
it "should output indicating invalidating on all base urls" do
|
|
68
|
+
base_urls_escaped = options[:base_urls].map { |base_url| Regexp.escape(base_url) }
|
|
69
|
+
expect { subject.invalidate(options, files) }.to output(/#{base_urls_escaped.join(".+")}/m).to_stdout
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
it "should output saying success checkmarks" do
|
|
73
|
+
expect { subject.invalidate(options, files) }.to output(/✔/).to_stdout
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
context "and errors occurs when purging" do
|
|
77
|
+
before do
|
|
78
|
+
allow(double_cloudflare).to receive(:zone_file_purge).and_raise(StandardError)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
it "should output saying error information" do
|
|
82
|
+
expect { subject.invalidate(options, files) }.to output(/error: StandardError/).to_stdout
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
context "environment variables used for credentials" do
|
|
88
|
+
before do
|
|
89
|
+
allow(ENV).to receive(:[])
|
|
90
|
+
allow(ENV).to receive(:[]).with("CLOUDFLARE_CLIENT_API_KEY").and_return("111111111111111111111")
|
|
91
|
+
allow(ENV).to receive(:[]).with("CLOUDFLARE_EMAIL").and_return("test-env@example.com")
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
let(:options) do
|
|
95
|
+
{
|
|
96
|
+
zone: 'example.com',
|
|
97
|
+
base_urls: ['http://example.com', 'https://example.com']
|
|
98
|
+
}
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
it "should connect to cloudflare with environment variable credentails" do
|
|
102
|
+
expect(::CloudFlare).to receive(:connection).with("111111111111111111111", "test-env@example.com")
|
|
103
|
+
subject.invalidate(options, files)
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "should not raise errors" do
|
|
107
|
+
subject.invalidate(options, files)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
context "if client_api_key not provided" do
|
|
112
|
+
before do
|
|
113
|
+
allow(ENV).to receive(:[])
|
|
114
|
+
allow(ENV).to receive(:[]).with("CLOUDFLARE_CLIENT_API_KEY").and_return(nil)
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
let(:options) do
|
|
118
|
+
{
|
|
119
|
+
email: 'test@example.com',
|
|
120
|
+
zone: 'example.com',
|
|
121
|
+
base_urls: ['http://example.com', 'https://example.com']
|
|
122
|
+
}
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
it "should raise error" do
|
|
126
|
+
expect { subject.invalidate(options, files) }.to raise_error(RuntimeError)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
it "should output saying error" do
|
|
130
|
+
expect { subject.invalidate(options, files) rescue nil }.to output(/Error: Configuration key cloudflare\[:client_api_key\] is missing\./).to_stdout
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
context "if email not provided" do
|
|
135
|
+
before do
|
|
136
|
+
allow(ENV).to receive(:[])
|
|
137
|
+
allow(ENV).to receive(:[]).with("CLOUDFLARE_EMAIL").and_return(nil)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
let(:options) do
|
|
141
|
+
{
|
|
142
|
+
client_api_key: '000000000000000000000',
|
|
143
|
+
zone: 'example.com',
|
|
144
|
+
base_urls: ['http://example.com', 'https://example.com']
|
|
145
|
+
}
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
it "should raise error" do
|
|
149
|
+
expect { subject.invalidate(options, files) }.to raise_error(RuntimeError)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
it "should output saying error" do
|
|
153
|
+
expect { subject.invalidate(options, files) rescue nil }.to output(/Error: Configuration key cloudflare\[:email\] is missing\./).to_stdout
|
|
154
|
+
end
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
context "if zone not provided" do
|
|
158
|
+
let(:options) do
|
|
159
|
+
{
|
|
160
|
+
client_api_key: '000000000000000000000',
|
|
161
|
+
email: 'test@example.com',
|
|
162
|
+
base_urls: ['http://example.com', 'https://example.com']
|
|
163
|
+
}
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
it "should raise error" do
|
|
167
|
+
expect { subject.invalidate(options, files) }.to raise_error(RuntimeError)
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
it "should output saying error" do
|
|
171
|
+
expect { subject.invalidate(options, files) rescue nil }.to output(/Error: Configuration key cloudflare\[:zone\] is missing\./).to_stdout
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
context "if base_urls not provided" do
|
|
176
|
+
let(:options) do
|
|
177
|
+
{
|
|
178
|
+
client_api_key: '000000000000000000000',
|
|
179
|
+
email: 'test@example.com',
|
|
180
|
+
zone: 'example.com',
|
|
181
|
+
}
|
|
182
|
+
end
|
|
183
|
+
|
|
184
|
+
it "should raise error" do
|
|
185
|
+
expect { subject.invalidate(options, files) }.to raise_error(RuntimeError)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
it "should output saying error" do
|
|
189
|
+
expect { subject.invalidate(options, files) rescue nil }.to output(/Error: Configuration key cloudflare\[:base_urls\] is missing\./).to_stdout
|
|
190
|
+
end
|
|
191
|
+
end
|
|
192
|
+
|
|
193
|
+
context "if base_urls is a String" do
|
|
194
|
+
let(:options) do
|
|
195
|
+
{
|
|
196
|
+
client_api_key: '000000000000000000000',
|
|
197
|
+
email: 'test@example.com',
|
|
198
|
+
zone: 'example.com',
|
|
199
|
+
base_urls: 'http://sub.example.com'
|
|
200
|
+
}
|
|
201
|
+
end
|
|
202
|
+
|
|
203
|
+
it "should not raise error" do
|
|
204
|
+
expect { subject.invalidate(options, files) }.to_not raise_error
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
it "should output indicating invalidating on the one base url" do
|
|
208
|
+
base_url_escaped = Regexp.escape(options[:base_urls])
|
|
209
|
+
expect { subject.invalidate(options, files) }.to output(/#{base_url_escaped}/).to_stdout
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
|
|
213
|
+
context "if base_urls is an empty Array" do
|
|
214
|
+
let(:options) do
|
|
215
|
+
{
|
|
216
|
+
client_api_key: '000000000000000000000',
|
|
217
|
+
email: 'test@example.com',
|
|
218
|
+
zone: 'example.com',
|
|
219
|
+
base_urls: []
|
|
220
|
+
}
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
it "should raise error" do
|
|
224
|
+
expect { subject.invalidate(options, files) }.to raise_error(RuntimeError)
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
it "should output saying error" do
|
|
228
|
+
expect { subject.invalidate(options, files) rescue nil }.to output(/Error: Configuration key cloudflare\[:base_urls\] is missing\./).to_stdout
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
|
|
232
|
+
context "if base_urls is not an Array or String" do
|
|
233
|
+
let(:options) do
|
|
234
|
+
{
|
|
235
|
+
client_api_key: '000000000000000000000',
|
|
236
|
+
email: 'test@example.com',
|
|
237
|
+
zone: 'example.com',
|
|
238
|
+
base_urls: 200
|
|
239
|
+
}
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
it "should raise error" do
|
|
243
|
+
expect { subject.invalidate(options, files) }.to raise_error(RuntimeError)
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
it "should output saying error" do
|
|
247
|
+
expect { subject.invalidate(options, files) rescue nil }.to output(/Error: Configuration key cloudflare\[:base_urls\] must be an array and contain at least one base url\./).to_stdout
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
end
|
|
251
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
require 'spec_helper'
|
|
2
|
+
require 'lib/middleman-cdn/cdns/base_protocol'
|
|
3
|
+
require 'fog/aws/models/cdn/distributions'
|
|
4
|
+
|
|
5
|
+
describe Middleman::Cli::CloudFrontCDN do
|
|
6
|
+
it_behaves_like "BaseCDN"
|
|
7
|
+
|
|
8
|
+
describe '.key' do
|
|
9
|
+
it "should be 'cloudfront'" do
|
|
10
|
+
expect(described_class.key).to eq("cloudfront")
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
describe '.example_configuration_elements' do
|
|
15
|
+
it "should contain these keys" do
|
|
16
|
+
required_keys = [:access_key_id, :secret_access_key, :distribution_id]
|
|
17
|
+
expect(described_class.example_configuration_elements.keys).to eq(required_keys)
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
describe '#invalidate' do
|
|
22
|
+
let(:options) do
|
|
23
|
+
{
|
|
24
|
+
access_key_id: 'access_key_id_123',
|
|
25
|
+
secret_access_key: 'secret_access_key_123',
|
|
26
|
+
distribution_id: 'distribution_id_123'
|
|
27
|
+
}
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
let(:double_cloudfront) { double('cloudfront', distributions: double('distributions')) }
|
|
31
|
+
let(:double_distribution) { double('distribution', invalidations: double('invalidations')) }
|
|
32
|
+
|
|
33
|
+
let(:files) { [ "/index.html", "/", "/test/index.html", "/test/image.png" ] }
|
|
34
|
+
|
|
35
|
+
before do
|
|
36
|
+
allow(::Fog::CDN).to receive(:new).and_return(double_cloudfront)
|
|
37
|
+
allow(double_cloudfront.distributions).to receive(:get).and_return(double_distribution)
|
|
38
|
+
allow(double_distribution.invalidations).to receive(:create).and_return(double('invalidation', status: 'InProgress', wait_for: ->{}, ready?: true))
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
it 'gets the correct distribution' do
|
|
42
|
+
expect(double_cloudfront.distributions).to receive(:get).with('distribution_id_123')
|
|
43
|
+
subject.invalidate(options, files)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
context 'when the amount of files to invalidate is under the limit' do
|
|
47
|
+
it 'divides them up in packages and creates one invalidation per package' do
|
|
48
|
+
files = (1..Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT).map do |i|
|
|
49
|
+
"file_#{i}"
|
|
50
|
+
end
|
|
51
|
+
expect(double_distribution.invalidations).to receive(:create).once.with(paths: files)
|
|
52
|
+
subject.invalidate(options, files)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
context 'when the amount of files to invalidate is over the limit' do
|
|
57
|
+
it 'creates only one invalidation with all of them' do
|
|
58
|
+
files = (1..(Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT * 3)).map do |i|
|
|
59
|
+
"file_#{i}"
|
|
60
|
+
end
|
|
61
|
+
expect(double_distribution.invalidations).to receive(:create).once.with(paths: files[0, Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT])
|
|
62
|
+
expect(double_distribution.invalidations).to receive(:create).once.with(paths: files[Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT, Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT])
|
|
63
|
+
expect(double_distribution.invalidations).to receive(:create).once.with(paths: files[Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT * 2, Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT])
|
|
64
|
+
subject.invalidate(options, files)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
require 'spec_helper'
|
|
2
|
-
|
|
3
2
|
require 'fog/aws/models/cdn/distributions'
|
|
4
3
|
|
|
5
4
|
describe Middleman::Cli::CDN do
|
|
@@ -12,48 +11,13 @@ describe Middleman::Cli::CDN do
|
|
|
12
11
|
secret_access_key: 'secret_access_key_123',
|
|
13
12
|
distribution_id: 'distribution_id_123',
|
|
14
13
|
},
|
|
15
|
-
filter:
|
|
14
|
+
filter: /.*/,
|
|
16
15
|
after_build: 'after_build_123'
|
|
17
16
|
})
|
|
18
17
|
end
|
|
19
18
|
let(:distribution) { double('distribution', invalidations: double('invalidations')) }
|
|
20
19
|
|
|
21
20
|
describe '#invalidate' do
|
|
22
|
-
|
|
23
|
-
allow_any_instance_of(Fog::CDN::AWS::Distributions).to receive(:get).and_return(distribution)
|
|
24
|
-
allow(distribution.invalidations).to receive(:create) do
|
|
25
|
-
double('invalidation', status: 'InProgress', wait_for: ->{} )
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
it 'gets the correct distribution' do
|
|
30
|
-
allow(cdn).to receive(:list_files).and_return ['index.html']
|
|
31
|
-
expect_any_instance_of(Fog::CDN::AWS::Distributions).to receive(:get).with('distribution_id_123')
|
|
32
|
-
cdn.invalidate(options)
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
context 'when the amount of files to invalidate is under the limit' do
|
|
36
|
-
it 'divides them up in packages and creates one invalidation per package' do
|
|
37
|
-
files = (1..Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT).map do |i|
|
|
38
|
-
"file_#{i}"
|
|
39
|
-
end
|
|
40
|
-
allow(cdn).to receive(:list_files).and_return files
|
|
41
|
-
expect(distribution.invalidations).to receive(:create).once.with(paths: files)
|
|
42
|
-
cdn.invalidate(options)
|
|
43
|
-
end
|
|
44
|
-
end
|
|
45
|
-
|
|
46
|
-
context 'when the amount of files to invalidate is over the limit' do
|
|
47
|
-
it 'creates only one invalidation with all of them' do
|
|
48
|
-
files = (1..(Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT * 3)).map do |i|
|
|
49
|
-
"file_#{i}"
|
|
50
|
-
end
|
|
51
|
-
allow(cdn).to receive(:list_files).and_return files
|
|
52
|
-
expect(distribution.invalidations).to receive(:create).once.with(paths: files[0, Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT])
|
|
53
|
-
expect(distribution.invalidations).to receive(:create).once.with(paths: files[Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT, Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT])
|
|
54
|
-
expect(distribution.invalidations).to receive(:create).once.with(paths: files[Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT * 2, Middleman::Cli::CloudFrontCDN::INVALIDATION_LIMIT])
|
|
55
|
-
cdn.invalidate(options)
|
|
56
|
-
end
|
|
57
|
-
end
|
|
21
|
+
# TODO
|
|
58
22
|
end
|
|
59
23
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: middleman-cdn
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Leigh McCulloch
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2014-07-
|
|
11
|
+
date: 2014-07-15 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: fog
|
|
@@ -41,73 +41,31 @@ dependencies:
|
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: colorize
|
|
43
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: cucumber
|
|
57
|
-
requirement: !ruby/object:Gem::Requirement
|
|
58
|
-
requirements:
|
|
59
|
-
- - "~>"
|
|
60
|
-
- !ruby/object:Gem::Version
|
|
61
|
-
version: '1.3'
|
|
62
|
-
type: :development
|
|
63
|
-
prerelease: false
|
|
64
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
65
|
-
requirements:
|
|
66
|
-
- - "~>"
|
|
67
|
-
- !ruby/object:Gem::Version
|
|
68
|
-
version: '1.3'
|
|
69
|
-
- !ruby/object:Gem::Dependency
|
|
70
|
-
name: aruba
|
|
71
|
-
requirement: !ruby/object:Gem::Requirement
|
|
72
|
-
requirements:
|
|
73
|
-
- - "~>"
|
|
74
|
-
- !ruby/object:Gem::Version
|
|
75
|
-
version: '0.5'
|
|
76
|
-
type: :development
|
|
77
|
-
prerelease: false
|
|
78
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
79
44
|
requirements:
|
|
80
45
|
- - "~>"
|
|
81
46
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '0.
|
|
83
|
-
|
|
84
|
-
name: fivemat
|
|
85
|
-
requirement: !ruby/object:Gem::Requirement
|
|
86
|
-
requirements:
|
|
87
|
-
- - "~>"
|
|
88
|
-
- !ruby/object:Gem::Version
|
|
89
|
-
version: '1.3'
|
|
90
|
-
type: :development
|
|
47
|
+
version: '0.7'
|
|
48
|
+
type: :runtime
|
|
91
49
|
prerelease: false
|
|
92
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
51
|
requirements:
|
|
94
52
|
- - "~>"
|
|
95
53
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '
|
|
54
|
+
version: '0.7'
|
|
97
55
|
- !ruby/object:Gem::Dependency
|
|
98
|
-
name:
|
|
56
|
+
name: activesupport
|
|
99
57
|
requirement: !ruby/object:Gem::Requirement
|
|
100
58
|
requirements:
|
|
101
59
|
- - "~>"
|
|
102
60
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: '
|
|
104
|
-
type: :
|
|
61
|
+
version: '4.1'
|
|
62
|
+
type: :runtime
|
|
105
63
|
prerelease: false
|
|
106
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
65
|
requirements:
|
|
108
66
|
- - "~>"
|
|
109
67
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: '
|
|
68
|
+
version: '4.1'
|
|
111
69
|
- !ruby/object:Gem::Dependency
|
|
112
70
|
name: rake
|
|
113
71
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -150,20 +108,6 @@ dependencies:
|
|
|
150
108
|
- - "~>"
|
|
151
109
|
- !ruby/object:Gem::Version
|
|
152
110
|
version: '3.0'
|
|
153
|
-
- !ruby/object:Gem::Dependency
|
|
154
|
-
name: activesupport
|
|
155
|
-
requirement: !ruby/object:Gem::Requirement
|
|
156
|
-
requirements:
|
|
157
|
-
- - "~>"
|
|
158
|
-
- !ruby/object:Gem::Version
|
|
159
|
-
version: '4.1'
|
|
160
|
-
type: :development
|
|
161
|
-
prerelease: false
|
|
162
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
163
|
-
requirements:
|
|
164
|
-
- - "~>"
|
|
165
|
-
- !ruby/object:Gem::Version
|
|
166
|
-
version: '4.1'
|
|
167
111
|
description: Invalidate a specific set of files in your CloudFlare or CloudFront cache
|
|
168
112
|
email:
|
|
169
113
|
executables: []
|
|
@@ -173,13 +117,12 @@ files:
|
|
|
173
117
|
- ".gitignore"
|
|
174
118
|
- ".travis.yml"
|
|
175
119
|
- Gemfile
|
|
176
|
-
- Guardfile
|
|
177
120
|
- LICENSE
|
|
178
121
|
- README-cloudflare-pagerule-example.png
|
|
179
122
|
- README.md
|
|
180
123
|
- Rakefile
|
|
181
|
-
- features/support/env.rb
|
|
182
124
|
- lib/middleman-cdn.rb
|
|
125
|
+
- lib/middleman-cdn/cdns/base.rb
|
|
183
126
|
- lib/middleman-cdn/cdns/cloudflare.rb
|
|
184
127
|
- lib/middleman-cdn/cdns/cloudfront.rb
|
|
185
128
|
- lib/middleman-cdn/commands.rb
|
|
@@ -187,6 +130,9 @@ files:
|
|
|
187
130
|
- lib/middleman-cdn/version.rb
|
|
188
131
|
- lib/middleman_extension.rb
|
|
189
132
|
- middleman-cdn.gemspec
|
|
133
|
+
- spec/lib/middleman-cdn/cdns/base_protocol.rb
|
|
134
|
+
- spec/lib/middleman-cdn/cdns/cloudflare_spec.rb
|
|
135
|
+
- spec/lib/middleman-cdn/cdns/cloudfront_spec.rb
|
|
190
136
|
- spec/lib/middleman-cdn/commands_spec.rb
|
|
191
137
|
- spec/spec_helper.rb
|
|
192
138
|
homepage: https://github.com/leighmcculloch/middleman-cdn
|
|
@@ -212,5 +158,4 @@ rubygems_version: 2.2.2
|
|
|
212
158
|
signing_key:
|
|
213
159
|
specification_version: 4
|
|
214
160
|
summary: Invalidate CloudFlare or CloudFront cache after deployment
|
|
215
|
-
test_files:
|
|
216
|
-
- features/support/env.rb
|
|
161
|
+
test_files: []
|
data/Guardfile
DELETED
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
guard 'rspec', cli: '--drb --profile', all_after_pass: false do
|
|
2
|
-
# Specs
|
|
3
|
-
watch(%r(^spec/.+_spec\.rb$))
|
|
4
|
-
watch('spec/spec_helper.rb') { 'spec' }
|
|
5
|
-
watch(%r(^spec/support/(.+)\.rb$)) { 'spec' }
|
|
6
|
-
|
|
7
|
-
# Files
|
|
8
|
-
watch(%r(^lib/(.+)\.rb$)) { |m| "spec/lib/#{m[1]}_spec.rb" }
|
|
9
|
-
end
|
data/features/support/env.rb
DELETED