puppet-library 0.6.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,15 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 6f9c3cf2e116027a1009cf54a51a6ba183de0580
4
- data.tar.gz: ef8af80971ad97d5aca06fd4cb011c48ed4645bf
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZWU3ZDcxMTYwNTRlYzU4MmI0M2UxN2Y1NWJjZDBmZTdmNjEzNTQzMg==
5
+ data.tar.gz: !binary |-
6
+ Yzc2ZGY1NDNmZGRiYzI5ZjBjYzRkZDhlNmI4YmMyNmEwYThlZWM5Zg==
5
7
  SHA512:
6
- metadata.gz: a695a4a49383c10faca50142781097319f9c5f1154f02ddf32b328f1ef6a71f5a7aa203936c96e77026cc9675ab6eb79297784a303a8bd156bfd2e33f0b39533
7
- data.tar.gz: 9a4c3cf05cba46d86208be6958d0c657e9858e54bf50e107fa9a7aebcac2eef7df8e0079ff71a5fe565bbd8315c50806828b7f078358b673dba02e9baeb07474
8
+ metadata.gz: !binary |-
9
+ OTBlNjVhZjI2ZGVlZDUyMDllNGNhODkxODQ4NzVlYmY2MjM0YmNmMGJlNzMy
10
+ MTBlMjFjOTZkYjM0MjcwY2UxNjllN2U2ZDg2MTliYjEwYzc5NWQxMzRiZjUw
11
+ MDg1YzMwMzEzZTJmYzY2ZTBjYjllYmM3ZTc1MzkxYzliMTFmZGI=
12
+ data.tar.gz: !binary |-
13
+ MmE5MjdiYjViMDYxYTU1ZTY5MDIwYzdhZDBkZGI5MmRlYTIyYzIwMDFmZjc4
14
+ OTY0ZmFkNGUyODE0ZDdjNzI0YzVjNzU4MWQ5NzE0OWE2MDEyMDY1YzA1ZDcy
15
+ YzlhOWY3NDhmZDIzN2Q0YjJmNTc1ZGQ2YmQyZTIyNWM0ZWY0ZTg=
data/CHANGELOG.yml CHANGED
@@ -42,6 +42,11 @@
42
42
  - Added module search field to web UI
43
43
  - tag: v0.6.0
44
44
  changes:
45
- - Add config API for running with Passenger
45
+ - Added config API for running with Passenger
46
46
  - Load configuration from a config file
47
47
  - Fixed version number bug that made the app crash with some Rubygems versions
48
+ - tag: v0.7.0
49
+ changes:
50
+ - Added new proxy forge that caches downloaded modules on disk
51
+ - Added `--cache-basedir` CLI option to make proxies cache downloaded modules on disk
52
+ - Fixed issue with forge proxying (#1)
data/README.md CHANGED
@@ -66,6 +66,10 @@ Serve modules from a remote forge as a proxy
66
66
 
67
67
  $ puppet-library --proxy http://forge.puppetlabs.com
68
68
 
69
+ Proxy a remote forge, caching downloaded modules on disk
70
+
71
+ $ puppet-library --proxy http://forge.puppetlabs.com --cache-basedir
72
+
69
73
  Serve modules on a specific port
70
74
 
71
75
  $ puppet-library --port 8888
data/Rakefile CHANGED
@@ -54,6 +54,13 @@ def ruby_version_supports_acceptance_tests?(version = RUBY_VERSION)
54
54
  end
55
55
  end
56
56
 
57
+ def offline?
58
+ Net::HTTP.get_response(URI.parse("http://forge.puppetlabs.com"))
59
+ return false
60
+ rescue
61
+ return true
62
+ end
63
+
57
64
  Coveralls::RakeTask.new
58
65
 
59
66
  desc "Run the specs"
@@ -78,6 +85,7 @@ if ruby_version_supports_integration_test?
78
85
  desc "Run the integration tests"
79
86
  RSpec::Core::RakeTask.new(:integration_test) do |rspec|
80
87
  rspec.pattern = "test/**/*_integration_test.rb"
88
+ rspec.rspec_opts = "--tag ~online" if offline?
81
89
  end
82
90
  else
83
91
  task :integration_test do
@@ -185,7 +193,7 @@ task "register-release", [:version] do |task, args|
185
193
  end
186
194
 
187
195
  def upload_release_notes(version)
188
- puts "Registering release notes for #{PuppetLibrary::VERSION}"
196
+ puts "Registering release notes for #{version}"
189
197
  github = Github.new
190
198
 
191
199
  unless version =~ /\d+\.\d+\.\d+/
data/TODO.yml CHANGED
@@ -1,13 +1,10 @@
1
1
  features:
2
2
  - disk cache:
3
- - Allow proxy to cache downloaded modules/API calls on disk
3
+ - use disk cache to respond to queries if remote API calls fail
4
4
  - |
5
5
  Accept --cache-dir option to specify a parent cache directory (people
6
6
  will need to embed the server or use a config file for more control)
7
- - Validate repo dirs (make sure they're readable)
8
- - Allow failover between module repositories
9
7
  - Web UI: asynchronous (index page loads too slowly)
10
- - Look in /etc/puppet-library.yml for config by default
11
8
  - Named subforges:
12
9
  - per-subforge queries
13
10
  - upload modules (web form and API)
@@ -18,3 +15,5 @@ features:
18
15
 
19
16
  dubious_features:
20
17
  - Make proxy cache TTL configurable
18
+ - Allow failover between module repositories
19
+ - Look in /etc/puppet-library.yml for config by default
@@ -20,6 +20,7 @@ module PuppetLibrary::Forge
20
20
  end
21
21
 
22
22
  require 'puppet_library/forge/abstract'
23
+ require 'puppet_library/forge/cache'
23
24
  require 'puppet_library/forge/directory'
24
25
  require 'puppet_library/forge/multi'
25
26
  require 'puppet_library/forge/proxy'
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2014 drrb
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'puppet_library/forge/proxy'
19
+ require 'puppet_library/http/http_client'
20
+
21
+ module PuppetLibrary::Forge
22
+ class Cache < Proxy
23
+ def initialize(url, cache_dir, http_client = PuppetLibrary::Http::HttpClient.new)
24
+ super(url, PuppetLibrary::Http::Cache::InMemory.new, PuppetLibrary::Http::Cache::Disk.new(cache_dir), http_client)
25
+ end
26
+ end
27
+ end
@@ -23,6 +23,8 @@ module PuppetLibrary::Forge
23
23
  class Directory < PuppetLibrary::Forge::Abstract
24
24
  def initialize(module_dir)
25
25
  super(self)
26
+ raise "Module directory '#{module_dir}' doesn't exist" unless File.directory? module_dir
27
+ raise "Module directory '#{module_dir}' isn't readable" unless File.executable? module_dir
26
28
  @module_dir = module_dir
27
29
  end
28
30
 
@@ -18,7 +18,6 @@
18
18
  require 'puppet_library/http/http_client'
19
19
  require 'puppet_library/http/cache/in_memory'
20
20
  require 'puppet_library/http/cache/noop'
21
- require 'puppet_library/http/url'
22
21
 
23
22
  module PuppetLibrary::Forge
24
23
  class Proxy
@@ -26,7 +25,7 @@ module PuppetLibrary::Forge
26
25
  query_cache = PuppetLibrary::Http::Cache::InMemory.new,
27
26
  download_cache = PuppetLibrary::Http::Cache::NoOp.new,
28
27
  http_client = PuppetLibrary::Http::HttpClient.new)
29
- @url = PuppetLibrary::Http::Url.normalize(url)
28
+ @url = url
30
29
  @http_client = http_client
31
30
  @query_cache = query_cache
32
31
  @download_cache = download_cache
@@ -42,7 +41,7 @@ module PuppetLibrary::Forge
42
41
  begin
43
42
  version_info = get_module_version(author, name, version)
44
43
  raise ModuleNotFound if version_info.nil?
45
- download_file(version_info["file"])
44
+ download_module(author, name, version, version_info["file"])
46
45
  rescue OpenURI::HTTPError
47
46
  raise ModuleNotFound
48
47
  end
@@ -59,7 +58,9 @@ module PuppetLibrary::Forge
59
58
 
60
59
  def get_module_metadata_with_dependencies(author, name, version)
61
60
  begin
62
- look_up_releases(author, name, version)
61
+ look_up_releases(author, name, version) do |full_name, release_info|
62
+ release_info["file"] = module_path_for(full_name, release_info["version"])
63
+ end
63
64
  rescue OpenURI::HTTPError
64
65
  raise ModuleNotFound
65
66
  end
@@ -78,15 +79,31 @@ module PuppetLibrary::Forge
78
79
  versions["#{author}/#{name}"]
79
80
  end
80
81
 
81
- def look_up_releases(author, name, version = nil)
82
+ def look_up_releases(author, name, version = nil, &block)
82
83
  version_query = version ? "&version=#{version}" : ""
83
84
  url = "/api/v1/releases.json?module=#{author}/#{name}#{version_query}"
84
- response = get(url)
85
- JSON.parse(response)
85
+ response_text = get(url)
86
+ response = JSON.parse(response_text)
87
+ process_releases_response(response, &block)
86
88
  end
87
89
 
88
- def download_file(file)
89
- @download_cache.get(file) do
90
+ def process_releases_response(response)
91
+ if block_given?
92
+ response.each do |full_name, release_infos|
93
+ release_infos.each do |release_info|
94
+ yield(full_name, release_info)
95
+ end
96
+ end
97
+ end
98
+ return response
99
+ end
100
+
101
+ def module_path_for(full_name, version)
102
+ "/modules/#{full_name.sub("/", "-")}-#{version}.tar.gz"
103
+ end
104
+
105
+ def download_module(author, name, version, file)
106
+ @download_cache.get("#{author}-#{name}-#{version}.tar.gz") do
90
107
  @http_client.download(url(file))
91
108
  end
92
109
  end
@@ -16,6 +16,7 @@
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
18
  module PuppetLibrary::Http::Cache
19
+ require 'puppet_library/http/cache/disk'
19
20
  require 'puppet_library/http/cache/in_memory'
20
21
  require 'puppet_library/http/cache/noop'
21
22
  end
@@ -0,0 +1,53 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2014 drrb
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ module PuppetLibrary::Http::Cache
19
+ class Disk
20
+ def initialize(directory)
21
+ @directory = directory
22
+ end
23
+
24
+ def get(path)
25
+ unless include? path
26
+ buffer = yield
27
+ save(path, buffer)
28
+ end
29
+ retrieve(path)
30
+ end
31
+
32
+ private
33
+ def include?(path)
34
+ File.exist? entry_path(path)
35
+ end
36
+
37
+ def save(path, buffer)
38
+ file_path = entry_path(path)
39
+ FileUtils.mkdir_p File.dirname(file_path)
40
+ File.open(file_path, "w") do |file|
41
+ file.write buffer.read
42
+ end
43
+ end
44
+
45
+ def retrieve(path)
46
+ File.open(entry_path(path))
47
+ end
48
+
49
+ def entry_path(path)
50
+ File.join(@directory, path)
51
+ end
52
+ end
53
+ end
@@ -15,10 +15,19 @@
15
15
  # You should have received a copy of the GNU General Public License
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
+ require 'uri'
19
+
18
20
  module PuppetLibrary::Http
19
21
  class Url
20
22
  def self.normalize(uri_string)
21
- unless uri_string =~ /^https?/
23
+ begin
24
+ url = URI.parse(uri_string)
25
+ rescue URI::InvalidURIError => e
26
+ raise PuppetLibrary::ExpectedError, "Invalid URL '#{uri_string}': #{e.message}"
27
+ end
28
+ if url.scheme
29
+ raise PuppetLibrary::ExpectedError, "Invalid URL '#{uri_string}': unsupported protocol '#{url.scheme}'" unless url.scheme =~ /^https?$/
30
+ else
22
31
  uri_string = "http://#{uri_string}"
23
32
  end
24
33
  uri_string.sub /\/$/, ""
@@ -42,6 +42,7 @@ module PuppetLibrary
42
42
  options = {}
43
43
  option_parser = OptionParser.new do |opts|
44
44
  opts.banner = "Usage: #{File.basename $0} [options]"
45
+ opts.version = VERSION
45
46
 
46
47
  opts.on("-c", "--config-file FILE", "Config file to read config values from") do |config_file|
47
48
  options[:config_file] = config_file
@@ -73,7 +74,11 @@ module PuppetLibrary
73
74
  options[:forges] << [Forge::Directory, module_dir]
74
75
  end
75
76
  opts.on("-x", "--proxy URL", "Remote forge to proxy (can be specified multiple times)") do |url|
76
- options[:forges] << [Forge::Proxy, url]
77
+ options[:forges] << [Forge::Proxy, sanitize_url(url)]
78
+ end
79
+
80
+ opts.on("--cache-basedir DIR", "Cache all proxies' downloaded modules under this directory") do |cache_basedir|
81
+ options[:cache_basedir] = cache_basedir
77
82
  end
78
83
  end
79
84
  begin
@@ -87,14 +92,15 @@ module PuppetLibrary
87
92
 
88
93
  def build_server(options)
89
94
  if options[:config_file]
90
- load_config(options)
95
+ load_config!(options)
91
96
  end
92
97
 
93
- load_defaults(options)
98
+ load_defaults!(options)
99
+ process_options!(options)
94
100
 
95
101
  Server.set_up do |server|
96
102
  options[:forges].each do |(forge_type, config)|
97
- subforge = forge_type.new(config)
103
+ subforge = forge_type.new(*config)
98
104
  server.forge subforge
99
105
  end
100
106
  end
@@ -126,7 +132,7 @@ module PuppetLibrary
126
132
  )
127
133
  end
128
134
 
129
- def load_config(options)
135
+ def load_config!(options)
130
136
  config = read_yaml_file(options[:config_file])
131
137
  options[:daemonize] = config["daemonize"]
132
138
  options[:port] = config["port"]
@@ -140,7 +146,7 @@ module PuppetLibrary
140
146
  options[:forges] = configured_forges + options[:forges]
141
147
  end
142
148
 
143
- def load_defaults(options)
149
+ def load_defaults!(options)
144
150
  options[:daemonize] ||= false
145
151
  options[:pidfile] ||= nil
146
152
  if options[:forges].empty?
@@ -148,9 +154,34 @@ module PuppetLibrary
148
154
  end
149
155
  end
150
156
 
157
+ def process_options!(options)
158
+ options[:forges].map! do |(forge_type, config)|
159
+ if forge_type == Forge::Proxy
160
+ end
161
+ if forge_type == Forge::Proxy && options[:cache_basedir]
162
+ cache_dir = File.join(options[:cache_basedir], url_hostname(config))
163
+ [ Forge::Cache, [ config, sanitize_path(cache_dir) ] ]
164
+ else
165
+ [ forge_type, config ]
166
+ end
167
+ end
168
+ end
169
+
151
170
  def read_yaml_file(path)
152
171
  YAML.load_file(File.expand_path(path)) || {}
153
172
  end
173
+
174
+ def sanitize_url(url)
175
+ Http::Url.normalize(url)
176
+ end
177
+
178
+ def sanitize_path(path)
179
+ File.expand_path path
180
+ end
181
+
182
+ def url_hostname(url)
183
+ URI.parse(Http::Url.normalize(url)).host
184
+ end
154
185
  end
155
186
 
156
187
  class ExpectedError < StandardError
@@ -68,12 +68,15 @@ module PuppetLibrary
68
68
  begin
69
69
  @forge.get_module_metadata(author, module_name).to_json
70
70
  rescue Forge::ModuleNotFound
71
- status 410
72
- {"error" => "Could not find module \"#{module_name}\""}.to_json
71
+ halt 410, {"error" => "Could not find module \"#{module_name}\""}.to_json
73
72
  end
74
73
  end
75
74
 
76
75
  get "/api/v1/releases.json" do
76
+ unless params[:module]
77
+ halt 400, {"error" => "The number of version constraints in the query does not match the number of module names"}.to_json
78
+ end
79
+
77
80
  author, module_name = params[:module].split "/"
78
81
  version = params[:version]
79
82
  begin
@@ -92,11 +95,12 @@ module PuppetLibrary
92
95
  content_type "application/octet-stream"
93
96
 
94
97
  begin
95
- @forge.get_module_buffer(author, name, version).tap do
98
+ buffer = @forge.get_module_buffer(author, name, version).tap do
96
99
  attachment "#{author}-#{name}-#{version}.tar.gz"
97
100
  end
101
+ [ 200, { "Content-Length" => buffer.size.to_s }, buffer ]
98
102
  rescue Forge::ModuleNotFound
99
- status 404
103
+ halt 404
100
104
  end
101
105
  end
102
106
 
@@ -16,5 +16,5 @@
16
16
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
17
 
18
18
  module PuppetLibrary
19
- VERSION = "0.6.0"
19
+ VERSION = "0.7.0"
20
20
  end
@@ -0,0 +1,67 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2014 drrb
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'spec_helper'
19
+
20
+ module PuppetLibrary::Forge
21
+ describe Cache do
22
+ let(:cache_dir) { Tempdir.create("module-cache") }
23
+ let(:http_client) { double(PuppetLibrary::Http::HttpClient) }
24
+ let(:forge) { Cache.new("http://forge.example.com", cache_dir, http_client) }
25
+
26
+ it "is a proxy" do
27
+ expect(forge).to be_a Proxy
28
+ end
29
+
30
+ describe "#get_module_buffer" do
31
+ before do
32
+ allow(http_client).to receive(:get).
33
+ with("http://forge.example.com/api/v1/releases.json?module=puppetlabs/apache").
34
+ and_return('{"puppetlabs/apache":[{"version":"1.0.0","file":"/puppetlabs/apache.tgz","dependencies":[["puppetlabs/concat",">= 1.0.0"],["puppetlabs/stdlib","~> 2.0.0"]]},{"version":"2.0.0","dependencies":[]}]}')
35
+ end
36
+
37
+ context "the first time it's called" do
38
+ it "downloads the module to disk and serves it" do
39
+ file_buffer = StringIO.new("apache module")
40
+ expect(http_client).to receive(:download).
41
+ with("http://forge.example.com/puppetlabs/apache.tgz").
42
+ and_return(file_buffer)
43
+
44
+ buffer = forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
45
+
46
+ downloaded_file = File.join(cache_dir, "puppetlabs-apache-1.0.0.tar.gz")
47
+ expect(File.read downloaded_file).to eq "apache module"
48
+ expect(buffer.read).to eq "apache module"
49
+ end
50
+ end
51
+
52
+ context "the second time it's called" do
53
+ it "serves the cached module from the disk" do
54
+ cached_module = File.join(cache_dir, "puppetlabs-apache-1.0.0.tar.gz")
55
+ File.open(cached_module, "w") do |file|
56
+ file.write "apache module"
57
+ end
58
+ expect(http_client).not_to receive(:download)
59
+
60
+ buffer = forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
61
+
62
+ expect(buffer.read).to eq "apache module"
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -19,18 +19,38 @@ require 'spec_helper'
19
19
  module PuppetLibrary::Forge
20
20
  describe Directory do
21
21
  include ModuleSpecHelper
22
- include FileUtils
23
22
 
24
- let(:module_dir) { Tempfile.new("module_dir").path }
23
+ let(:module_dir) { Tempdir.create("module_dir") }
25
24
  let(:module_repo) { Directory.new(module_dir) }
26
25
 
27
- before do
26
+ after do
28
27
  rm_rf module_dir
29
- mkdir_p module_dir
30
28
  end
31
29
 
32
- after do
33
- rm_rf module_dir
30
+ describe "#initialize" do
31
+ context "when the module directory doesn't exist" do
32
+ before do
33
+ rm_rf module_dir
34
+ end
35
+
36
+ it "raises an error" do
37
+ expect {
38
+ Directory.new(module_dir)
39
+ }.to raise_error /Module directory .* doesn't exist/
40
+ end
41
+ end
42
+
43
+ context "when the module directory isn't readable" do
44
+ before do
45
+ chmod 0400, module_dir
46
+ end
47
+
48
+ it "raises an error" do
49
+ expect {
50
+ Directory.new(module_dir)
51
+ }.to raise_error /Module directory .* isn't readable/
52
+ end
53
+ end
34
54
  end
35
55
 
36
56
  describe "#get_module" do
@@ -24,24 +24,6 @@ module PuppetLibrary::Forge
24
24
  let(:download_cache) { PuppetLibrary::Http::Cache::InMemory.new }
25
25
  let(:forge) { Proxy.new("http://puppetforge.example.com", query_cache, download_cache, http_client) }
26
26
 
27
- describe "url" do
28
- it "defaults to HTTP, when protocol not specified" do
29
- forge = Proxy.new("forge.puppetlabs.com", query_cache, download_cache, http_client)
30
-
31
- expect(http_client).to receive(:get).with("http:\/\/forge.puppetlabs.com/puppetlabs/apache.json").and_return('{"puppetlabs/apache":[]}')
32
-
33
- forge.get_module_metadata("puppetlabs", "apache")
34
- end
35
-
36
- it "copes with a trailing slash" do
37
- forge = Proxy.new("forge.puppetlabs.com/", query_cache, download_cache, http_client)
38
-
39
- expect(http_client).to receive(:get).with("http:\/\/forge.puppetlabs.com/puppetlabs/apache.json").and_return('{"puppetlabs/apache":[]}')
40
-
41
- forge.get_module_metadata("puppetlabs", "apache")
42
- end
43
- end
44
-
45
27
  describe "#search_modules" do
46
28
  it "forwards the request directly" do
47
29
  search_results = '["a","b","c"]'
@@ -180,15 +162,16 @@ module PuppetLibrary::Forge
180
162
  end
181
163
 
182
164
  context "when the module is found" do
183
- it "forwards the request directly" do
184
- response = '{"puppetlabs/apache":[{"version":"1.0.0","dependencies":[["puppetlabs/concat",">= 1.0.0"],["puppetlabs/stdlib","~> 2.0.0"]]},{"version":"2.0.0","dependencies":[]}]}'
165
+ it "forwards the request directly, but adjusts the module download locations" do
166
+ original_response = '{"puppetlabs/apache":[{"version":"1.0.0","file":"/puppetlabs/apache/1.0.0.tar.gz","dependencies":[["puppetlabs/concat",">= 1.0.0"],["puppetlabs/stdlib","~> 2.0.0"]]},{"version":"2.0.0","file":"/puppetlabs/apache/2.0.0.tar.gz","dependencies":[]}]}'
167
+ doctored_response = '{"puppetlabs/apache":[{"version":"1.0.0","file":"/modules/puppetlabs-apache-1.0.0.tar.gz","dependencies":[["puppetlabs/concat",">= 1.0.0"],["puppetlabs/stdlib","~> 2.0.0"]]},{"version":"2.0.0","file":"/modules/puppetlabs-apache-2.0.0.tar.gz","dependencies":[]}]}'
185
168
  expect(http_client).to receive(:get).
186
169
  with("http://puppetforge.example.com/api/v1/releases.json?module=puppetlabs/apache&version=1.0.0").
187
- and_return(response)
170
+ and_return(original_response)
188
171
 
189
172
  result = forge.get_module_metadata_with_dependencies("puppetlabs", "apache", "1.0.0")
190
173
 
191
- expect(result).to eq JSON.parse(response)
174
+ expect(result).to eq JSON.parse(doctored_response)
192
175
  end
193
176
 
194
177
  it "caches the result" do
@@ -0,0 +1,57 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2014 drrb
4
+ #
5
+ # This program is free software: you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation, either version 3 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
17
+
18
+ require 'spec_helper'
19
+
20
+ module PuppetLibrary::Http::Cache
21
+ describe Disk do
22
+ let(:cache_dir) { Tempdir.new("modulecache").path }
23
+ let(:cache) { Disk.new(cache_dir) }
24
+
25
+ after do
26
+ rm_rf cache_dir
27
+ end
28
+
29
+ describe "#get" do
30
+ context "the first time it's called" do
31
+ it "returns the value from the block" do
32
+ buffer = StringIO.new "hello"
33
+
34
+ result = cache.get("my-file") { buffer }
35
+
36
+ expect(result.read).to eq "hello"
37
+ end
38
+
39
+ it "saves the content to disk" do
40
+ buffer = StringIO.new "hello"
41
+
42
+ result = cache.get("dir/my-file") { buffer }
43
+
44
+ path = File.join(cache_dir, "dir", "my-file")
45
+ expect(File.read(path)).to eq "hello"
46
+ end
47
+ end
48
+
49
+ context "the second time it's called" do
50
+ it "reads the config from the disk" do
51
+ cache.get("my-file") { StringIO.new "hello" }
52
+ result = cache.get("my-file") { raise "shouldn't be called" }
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -34,7 +34,7 @@ module PuppetLibrary::Http::Cache
34
34
  context "the second time it's called" do
35
35
  it "returns the cached value" do
36
36
  cache.get("greeting") { "hello" }
37
- greeting = cache.get("greeting") { "hi" }
37
+ greeting = cache.get("greeting") { raise "shouldn't be called" }
38
38
 
39
39
  expect(greeting).to eq "hello"
40
40
  end
@@ -34,6 +34,22 @@ module PuppetLibrary::Http
34
34
  result = Url.normalize "http://localhost/"
35
35
  expect(result).to eq "http://localhost"
36
36
  end
37
+
38
+ context "when the URL has an invalid scheme" do
39
+ it "raises an error" do
40
+ expect {
41
+ Url.normalize "ftp://example.com"
42
+ }.to raise_exception /Invalid URL/
43
+ end
44
+ end
45
+
46
+ context "when the URL is invalid" do
47
+ it "raises an error" do
48
+ expect {
49
+ Url.normalize "a b"
50
+ }.to raise_exception /Invalid URL/
51
+ end
52
+ end
37
53
  end
38
54
  end
39
55
  end
@@ -140,6 +140,39 @@ module PuppetLibrary
140
140
 
141
141
  library.go(["--proxy", "http://forge1.example.com", "--proxy", "http://forge2.example.com"])
142
142
  end
143
+
144
+ context "when no protocol is specified" do
145
+ it "defaults to HTTP" do
146
+ expect(Forge::Proxy).to receive(:new).with("http://forge.example.com")
147
+
148
+ library.go(["--proxy", "forge.example.com"])
149
+ end
150
+ end
151
+
152
+ context "when the URL contains a trailing slash" do
153
+ it "removes the slash" do
154
+ expect(Forge::Proxy).to receive(:new).with("http://forge.example.com")
155
+
156
+ library.go(["--proxy", "http://forge.example.com/"])
157
+ end
158
+ end
159
+ end
160
+
161
+ context "when using --cache-basedir option" do
162
+ it "uses the specified directory to hold cache directories for all proxies" do
163
+ proxy1 = double('proxy')
164
+ expect(Forge::Cache).to receive(:new).with("http://forge1.example.com", "/var/modules/forge1.example.com").and_return(proxy1)
165
+ expect(forge).to receive(:add_forge).with(proxy1)
166
+ expect(Rack::Server).to receive(:start).with(default_options)
167
+
168
+ library.go(["--proxy", "http://forge1.example.com", "--cache-basedir", "/var/modules"])
169
+ end
170
+
171
+ it "expands the path specified" do
172
+ expect(Forge::Cache).to receive(:new).with("http://forge1.example.com", "/var/modules/forge1.example.com")
173
+
174
+ library.go(["--proxy", "http://forge1.example.com", "--cache-basedir", "/var/../var/modules"])
175
+ end
143
176
  end
144
177
 
145
178
  context "when using --module-dir option" do
@@ -172,8 +205,8 @@ module PuppetLibrary
172
205
  expect(log).to receive(:puts).with(/Host: default/)
173
206
  expect(log).to receive(:puts).with(/Server: default/)
174
207
  expect(log).to receive(:puts).with(/Forges:/)
175
- expect(log).to receive(:puts).with(/- PuppetLibrary::Forge::Directory: \.\/modules/)
176
- library.go(["--module-dir", "./modules"])
208
+ expect(log).to receive(:puts).with(/- PuppetLibrary::Forge::Proxy: http:\/\/forge.example.com/)
209
+ library.go(["--proxy", "http://forge.example.com"])
177
210
  end
178
211
  end
179
212
  end
data/spec/server_spec.rb CHANGED
@@ -196,6 +196,15 @@ module PuppetLibrary
196
196
  end
197
197
 
198
198
  describe "GET /api/v1/releases.json" do
199
+ context "when module parameter not specified" do
200
+ it "returns an error" do
201
+ get "/api/v1/releases.json"
202
+
203
+ expect(last_response.body).to eq('{"error":"The number of version constraints in the query does not match the number of module names"}')
204
+ expect(last_response.status).to eq(400)
205
+ end
206
+ end
207
+
199
208
  it "gets metadata for module and dependencies" do
200
209
  metadata = {
201
210
  "puppetlabs/apache" => [
data/spec/spec_helper.rb CHANGED
@@ -21,3 +21,21 @@ require 'module_spec_helper'
21
21
  require 'pry'
22
22
  require 'rack'
23
23
  require 'tempfile'
24
+ require 'fileutils'
25
+
26
+ include FileUtils
27
+
28
+ class Tempdir
29
+ attr_reader :path
30
+
31
+ def self.create(name)
32
+ Tempdir.new(name).path
33
+ end
34
+
35
+ def initialize(name)
36
+ file = Tempfile.new(name)
37
+ @path = file.path
38
+ file.unlink
39
+ FileUtils.mkdir @path
40
+ end
41
+ end
@@ -18,13 +18,32 @@
18
18
  require 'spec_helper'
19
19
  require 'open-uri'
20
20
 
21
+
22
+ RSpec::Matchers.define :be_cached do
23
+ match do |mod_file|
24
+ ! Dir[File.join(cache_dir, mod_file)].empty?
25
+ end
26
+ end
27
+
28
+ RSpec::Matchers.define :be_installed do
29
+ match do |mod_name|
30
+ File.directory?(File.join(project_dir, "modules", mod_name))
31
+ end
32
+ end
33
+
34
+ def write_puppetfile(content)
35
+ File.open("#{project_dir}/Puppetfile", "w") do |puppetfile|
36
+ puppetfile.puts content
37
+ end
38
+ end
39
+
21
40
  module PuppetLibrary
22
- describe "librarian-puppet integration test" do
41
+ describe "offline proxy" do
23
42
  include ModuleSpecHelper
24
- include FileUtils
25
43
 
26
- let(:module_dir) { Tempfile.new("module_dir").path }
27
- let(:project_dir) { Tempfile.new("project_dir").path }
44
+ let(:module_dir) { Tempdir.create("module_dir") }
45
+ let(:project_dir) { Tempdir.create("project_dir") }
46
+ let(:cache_dir) { Tempdir.create("cache_dir") }
28
47
  let(:start_dir) { pwd }
29
48
  let(:disk_forge) { Forge::Directory.new(module_dir) }
30
49
  let(:disk_server) do
@@ -45,7 +64,7 @@ module PuppetLibrary
45
64
  disk_rack_server.start
46
65
  end
47
66
  end
48
- let(:proxy_forge) { Forge::Proxy.new("http://localhost:9000") }
67
+ let(:proxy_forge) { Forge::Cache.new("http://localhost:9000", cache_dir) }
49
68
  let(:proxy_server) do
50
69
  Server.set_up do |server|
51
70
  server.forge proxy_forge
@@ -66,10 +85,6 @@ module PuppetLibrary
66
85
  end
67
86
 
68
87
  before do
69
- rm_rf module_dir
70
- rm_rf project_dir
71
- mkdir_p module_dir
72
- mkdir_p project_dir
73
88
  # Initialize to catch wiring errors
74
89
  disk_rack_server
75
90
  proxy_rack_server
@@ -84,15 +99,10 @@ module PuppetLibrary
84
99
  after do
85
100
  rm_rf module_dir
86
101
  rm_rf project_dir
102
+ rm_rf cache_dir
87
103
  cd start_dir
88
104
  end
89
105
 
90
- def write_puppetfile(content)
91
- File.open("#{project_dir}/Puppetfile", "w") do |puppetfile|
92
- puppetfile.puts content
93
- end
94
- end
95
-
96
106
  it "queries, downloads and searches through a proxy to a directory" do
97
107
  add_module("puppetlabs", "apache", "1.0.0") do |metadata|
98
108
  metadata["dependencies"] << { "name" => "puppetlabs/concat", "version_requirement" => ">= 2.0.0" }
@@ -108,10 +118,13 @@ module PuppetLibrary
108
118
 
109
119
  # Install modules through the proxy
110
120
  system "librarian-puppet install" or fail "call to puppet-library failed"
111
- expect(File.directory? "modules").to be true
112
- expect(File.directory? "modules/apache").to be true
113
- expect(File.directory? "modules/concat").to be true
114
- expect(File.directory? "modules/stdlib").to be true
121
+ expect("apache").to be_installed
122
+ expect("concat").to be_installed
123
+ expect("stdlib").to be_installed
124
+
125
+ expect("puppetlabs-apache-1.0.0.tar.gz").to be_cached
126
+ expect("puppetlabs-concat-2.0.0.tar.gz").to be_cached
127
+ expect("puppetlabs-stdlib-3.0.0.tar.gz").to be_cached
115
128
 
116
129
  # Search through the proxy
117
130
  search_results = JSON.parse(open("http://localhost:9001/modules.json").read)
@@ -123,4 +136,69 @@ module PuppetLibrary
123
136
  expect(found_modules["puppetlabs/stdlib"]).to eq "3.0.0"
124
137
  end
125
138
  end
139
+
140
+ describe "online proxy", :online => true do
141
+ include ModuleSpecHelper
142
+
143
+ let(:project_dir) { Tempdir.create("project_dir") }
144
+ let(:module_dir) { Tempdir.create("module_dir") }
145
+ let(:cache_dir) { Tempdir.create("cache_dir") }
146
+ let(:start_dir) { pwd }
147
+ let(:proxy_server) do
148
+ Server.set_up do |server|
149
+ server.forge Forge::Directory.new(module_dir)
150
+ server.forge Forge::Cache.new("http://forge.puppetlabs.com", cache_dir)
151
+ end
152
+ end
153
+ let(:proxy_rack_server) do
154
+ Rack::Server.new(
155
+ :app => proxy_server,
156
+ :Host => "localhost",
157
+ :Port => 9002,
158
+ :server => "webrick"
159
+ )
160
+ end
161
+ let(:proxy_server_runner) do
162
+ Thread.new do
163
+ proxy_rack_server.start
164
+ end
165
+ end
166
+
167
+ before do
168
+ # Initialize to catch wiring errors
169
+ proxy_rack_server
170
+
171
+ # Start the server
172
+ proxy_server_runner
173
+ start_dir
174
+ cd project_dir
175
+ end
176
+
177
+ after do
178
+ rm_rf module_dir
179
+ rm_rf project_dir
180
+ rm_rf cache_dir
181
+ cd start_dir
182
+ end
183
+
184
+ it "queries, downloads and searches through a proxy to a directory" do
185
+ add_module("drrb", "tomcat", "1.0.0") do |metadata|
186
+ metadata["dependencies"] << { "name" => "puppetlabs/apache", "version_requirement" => "0.9.0" }
187
+ end
188
+
189
+ write_puppetfile <<-EOF
190
+ forge 'http://localhost:9002'
191
+ mod 'drrb/tomcat'
192
+ EOF
193
+
194
+ # Install modules through the proxy
195
+ system "librarian-puppet install" or fail "call to puppet-library failed"
196
+ expect("tomcat").to be_installed
197
+ expect("apache").to be_installed
198
+ expect("concat").to be_installed
199
+ expect("stdlib").to be_installed
200
+
201
+ expect("puppetlabs-apache-*.tar.gz").to be_cached
202
+ end
203
+ end
126
204
  end
metadata CHANGED
@@ -1,55 +1,55 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet-library
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - drrb
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-03 00:00:00.000000000 Z
11
+ date: 2014-02-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - '>='
17
+ - - ! '>='
18
18
  - !ruby/object:Gem::Version
19
19
  version: '0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - '>='
24
+ - - ! '>='
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: json
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - '>='
31
+ - - ! '>='
32
32
  - !ruby/object:Gem::Version
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - '>='
38
+ - - ! '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: haml
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - '>='
45
+ - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
47
  version: '0'
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - '>='
52
+ - - ! '>='
53
53
  - !ruby/object:Gem::Version
54
54
  version: '0'
55
55
  - !ruby/object:Gem::Dependency
@@ -70,42 +70,42 @@ dependencies:
70
70
  name: coveralls
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - '>='
73
+ - - ! '>='
74
74
  - !ruby/object:Gem::Version
75
75
  version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - '>='
80
+ - - ! '>='
81
81
  - !ruby/object:Gem::Version
82
82
  version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: gitsu
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - '>='
87
+ - - ! '>='
88
88
  - !ruby/object:Gem::Version
89
89
  version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - '>='
94
+ - - ! '>='
95
95
  - !ruby/object:Gem::Version
96
96
  version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: librarian-puppet
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - '>='
101
+ - - ! '>='
102
102
  - !ruby/object:Gem::Version
103
103
  version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - '>='
108
+ - - ! '>='
109
109
  - !ruby/object:Gem::Version
110
110
  version: '0'
111
111
  - !ruby/object:Gem::Dependency
@@ -126,14 +126,14 @@ dependencies:
126
126
  name: pry
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - '>='
129
+ - - ! '>='
130
130
  - !ruby/object:Gem::Version
131
131
  version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - '>='
136
+ - - ! '>='
137
137
  - !ruby/object:Gem::Version
138
138
  version: '0'
139
139
  - !ruby/object:Gem::Dependency
@@ -154,140 +154,140 @@ dependencies:
154
154
  name: rack-test
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - '>='
157
+ - - ! '>='
158
158
  - !ruby/object:Gem::Version
159
159
  version: '0'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - '>='
164
+ - - ! '>='
165
165
  - !ruby/object:Gem::Version
166
166
  version: '0'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: rake
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - '>='
171
+ - - ! '>='
172
172
  - !ruby/object:Gem::Version
173
173
  version: '0'
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
- - - '>='
178
+ - - ! '>='
179
179
  - !ruby/object:Gem::Version
180
180
  version: '0'
181
181
  - !ruby/object:Gem::Dependency
182
182
  name: rspec
183
183
  requirement: !ruby/object:Gem::Requirement
184
184
  requirements:
185
- - - '>='
185
+ - - ! '>='
186
186
  - !ruby/object:Gem::Version
187
187
  version: '0'
188
188
  type: :development
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
- - - '>='
192
+ - - ! '>='
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: simplecov
197
197
  requirement: !ruby/object:Gem::Requirement
198
198
  requirements:
199
- - - '>='
199
+ - - ! '>='
200
200
  - !ruby/object:Gem::Version
201
201
  version: '0'
202
202
  type: :development
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
- - - '>='
206
+ - - ! '>='
207
207
  - !ruby/object:Gem::Version
208
208
  version: '0'
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: guard
211
211
  requirement: !ruby/object:Gem::Requirement
212
212
  requirements:
213
- - - '>='
213
+ - - ! '>='
214
214
  - !ruby/object:Gem::Version
215
215
  version: '0'
216
216
  type: :development
217
217
  prerelease: false
218
218
  version_requirements: !ruby/object:Gem::Requirement
219
219
  requirements:
220
- - - '>='
220
+ - - ! '>='
221
221
  - !ruby/object:Gem::Version
222
222
  version: '0'
223
223
  - !ruby/object:Gem::Dependency
224
224
  name: guard-rspec
225
225
  requirement: !ruby/object:Gem::Requirement
226
226
  requirements:
227
- - - '>='
227
+ - - ! '>='
228
228
  - !ruby/object:Gem::Version
229
229
  version: '0'
230
230
  type: :development
231
231
  prerelease: false
232
232
  version_requirements: !ruby/object:Gem::Requirement
233
233
  requirements:
234
- - - '>='
234
+ - - ! '>='
235
235
  - !ruby/object:Gem::Version
236
236
  version: '0'
237
237
  - !ruby/object:Gem::Dependency
238
238
  name: terminal-notifier-guard
239
239
  requirement: !ruby/object:Gem::Requirement
240
240
  requirements:
241
- - - '>='
241
+ - - ! '>='
242
242
  - !ruby/object:Gem::Version
243
243
  version: '0'
244
244
  type: :development
245
245
  prerelease: false
246
246
  version_requirements: !ruby/object:Gem::Requirement
247
247
  requirements:
248
- - - '>='
248
+ - - ! '>='
249
249
  - !ruby/object:Gem::Version
250
250
  version: '0'
251
251
  - !ruby/object:Gem::Dependency
252
252
  name: capybara
253
253
  requirement: !ruby/object:Gem::Requirement
254
254
  requirements:
255
- - - '>='
255
+ - - ! '>='
256
256
  - !ruby/object:Gem::Version
257
257
  version: '0'
258
258
  type: :development
259
259
  prerelease: false
260
260
  version_requirements: !ruby/object:Gem::Requirement
261
261
  requirements:
262
- - - '>='
262
+ - - ! '>='
263
263
  - !ruby/object:Gem::Version
264
264
  version: '0'
265
265
  - !ruby/object:Gem::Dependency
266
266
  name: nokogiri
267
267
  requirement: !ruby/object:Gem::Requirement
268
268
  requirements:
269
- - - '>='
269
+ - - ! '>='
270
270
  - !ruby/object:Gem::Version
271
271
  version: '0'
272
272
  type: :development
273
273
  prerelease: false
274
274
  version_requirements: !ruby/object:Gem::Requirement
275
275
  requirements:
276
- - - '>='
276
+ - - ! '>='
277
277
  - !ruby/object:Gem::Version
278
278
  version: '0'
279
279
  - !ruby/object:Gem::Dependency
280
280
  name: cucumber
281
281
  requirement: !ruby/object:Gem::Requirement
282
282
  requirements:
283
- - - '>='
283
+ - - ! '>='
284
284
  - !ruby/object:Gem::Version
285
285
  version: '0'
286
286
  type: :development
287
287
  prerelease: false
288
288
  version_requirements: !ruby/object:Gem::Requirement
289
289
  requirements:
290
- - - '>='
290
+ - - ! '>='
291
291
  - !ruby/object:Gem::Version
292
292
  version: '0'
293
293
  description: A Puppet module server
@@ -323,12 +323,14 @@ files:
323
323
  - lib/puppet_library/app/views/module_not_found.haml
324
324
  - lib/puppet_library/forge.rb
325
325
  - lib/puppet_library/forge/abstract.rb
326
+ - lib/puppet_library/forge/cache.rb
326
327
  - lib/puppet_library/forge/directory.rb
327
328
  - lib/puppet_library/forge/multi.rb
328
329
  - lib/puppet_library/forge/proxy.rb
329
330
  - lib/puppet_library/forge/search_result.rb
330
331
  - lib/puppet_library/http.rb
331
332
  - lib/puppet_library/http/cache.rb
333
+ - lib/puppet_library/http/cache/disk.rb
332
334
  - lib/puppet_library/http/cache/in_memory.rb
333
335
  - lib/puppet_library/http/cache/noop.rb
334
336
  - lib/puppet_library/http/http_client.rb
@@ -339,9 +341,11 @@ files:
339
341
  - lib/puppet_library/version.rb
340
342
  - puppet-library.gemspec
341
343
  - spec/forge/abstract_spec.rb
344
+ - spec/forge/cache_spec.rb
342
345
  - spec/forge/directory_spec.rb
343
346
  - spec/forge/multi_spec.rb
344
347
  - spec/forge/proxy_spec.rb
348
+ - spec/http/cache/disk_spec.rb
345
349
  - spec/http/cache/in_memory_spec.rb
346
350
  - spec/http/cache/noop_spec.rb
347
351
  - spec/http/http_client_spec.rb
@@ -362,17 +366,17 @@ require_paths:
362
366
  - lib
363
367
  required_ruby_version: !ruby/object:Gem::Requirement
364
368
  requirements:
365
- - - '>='
369
+ - - ! '>='
366
370
  - !ruby/object:Gem::Version
367
371
  version: '0'
368
372
  required_rubygems_version: !ruby/object:Gem::Requirement
369
373
  requirements:
370
- - - '>='
374
+ - - ! '>='
371
375
  - !ruby/object:Gem::Version
372
376
  version: '0'
373
377
  requirements: []
374
378
  rubyforge_project:
375
- rubygems_version: 2.0.3
379
+ rubygems_version: 2.2.1
376
380
  signing_key:
377
381
  specification_version: 4
378
382
  summary: Puppet Library is a private Puppet module server that's compatible with librarian-puppet.
@@ -383,9 +387,11 @@ test_files:
383
387
  - features/step_definitions/sinatra_steps.rb
384
388
  - features/support/env.rb
385
389
  - spec/forge/abstract_spec.rb
390
+ - spec/forge/cache_spec.rb
386
391
  - spec/forge/directory_spec.rb
387
392
  - spec/forge/multi_spec.rb
388
393
  - spec/forge/proxy_spec.rb
394
+ - spec/http/cache/disk_spec.rb
389
395
  - spec/http/cache/in_memory_spec.rb
390
396
  - spec/http/cache/noop_spec.rb
391
397
  - spec/http/http_client_spec.rb