puppet-library 0.9.0 → 0.9.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
- ---
2
- SHA1:
3
- metadata.gz: 957de9eb484e3ec881a524fe467b6ceab2575f34
4
- data.tar.gz: b3a3dbc2610ec8fcdc1064f9b745ea5ba9539e3d
5
- SHA512:
6
- metadata.gz: 9c8bf309ca1363ea52d83d144a1aea682c236c10a00ee7520a62608771f37d2cbfb7d16eb9f1267fd06ad4127aae612b2b1c0d042532a64999bfae8d27d69040
7
- data.tar.gz: 965b766bcc9d58bc6939ba454a937469a5db4fc9f23b82a2dfbce089bc5b3c4817583379a2444131b94a44506b74de66e2ba9bf2a53a2627639ceb18eef1093c
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 280994b916da7d8f05ba4cf98828e6459d6fdea4
4
+ data.tar.gz: d1654492cdb5e30855c62b5fbabf08d7c1cb38a5
5
+ SHA512:
6
+ metadata.gz: d518cbe064ed9c664fd2198d070ce7db2576c761d9526a52c3ee577d8f067c0183462027dd78420810f82c1262f8fa8d9ac5e39c64b93e6a70e19baa8aff4022
7
+ data.tar.gz: 28e347c2c9ed7215a6c2f2915264e463580d337e596464a6d5afddcb64d35bfec27b6a9be176712cb939f455f10b4694eea55adca0e98a90cb9d5f7337c953cc
data/CHANGELOG.yml CHANGED
@@ -57,3 +57,9 @@
57
57
  - tag: v0.9.0
58
58
  changes:
59
59
  - Added new source forge that serves modules from directories on disk
60
+ - tag: v0.9.1
61
+ changes:
62
+ - Fixed source forge bug that generated metadata incorrectly
63
+ - tag: v0.10.0
64
+ changes:
65
+ - Fixed imports to enable easier embedding of Puppet Library
data/Rakefile CHANGED
@@ -102,7 +102,7 @@ end
102
102
  task :default => [:test, 'coveralls:push']
103
103
 
104
104
  desc "Check it works on all local rubies"
105
- task :verify do
105
+ task :verify => 'test-imports' do
106
106
  versions = SUPPORTED_RUBY_VERSIONS
107
107
  puts "\nRunning Specs".green
108
108
  spec_results = versions.map do |ruby_version|
@@ -185,6 +185,7 @@ task "push-release" => ["check-license", :verify] do
185
185
  upload_release_notes(PuppetLibrary::VERSION)
186
186
 
187
187
  increment_version
188
+ git_push
188
189
  end
189
190
 
190
191
  desc "Increment version number and commit it"
@@ -197,6 +198,39 @@ task "register-release", [:version] do |task, args|
197
198
  upload_release_notes(args[:version])
198
199
  end
199
200
 
201
+ desc "Import files individually to make sure they can be imported externally"
202
+ task "test-imports" do
203
+ puts "Testing imports"
204
+ puts
205
+ Dir.chdir "lib"
206
+
207
+ paths = Dir["**/*.rb"].map {|f| f.sub /\.rb$/, "" }
208
+ paths = paths.sort_by {|p| p.count "/"}
209
+ errors = []
210
+ paths.each do |path|
211
+ print "importing #{path}..."
212
+ output = `ruby -e '$LOAD_PATH.unshift(File.expand_path(".")); require "#{path}"' 2>&1`
213
+ print " ["
214
+ if $?.success?
215
+ print "OK".green
216
+ else
217
+ print "FAIL".red
218
+ errors << "#{path}: #{output.red}"
219
+ end
220
+ puts "]"
221
+ end
222
+
223
+ unless errors.empty?
224
+ puts
225
+ puts
226
+ fail <<-EOFAILURE
227
+ Failed to import some files:
228
+
229
+ #{errors.join "\n\n"}
230
+ EOFAILURE
231
+ end
232
+ end
233
+
200
234
  def upload_release_notes(version)
201
235
  puts "Registering release notes for #{version}"
202
236
  github = Github.new
@@ -232,6 +266,10 @@ def upload_release_notes(version)
232
266
  puts "Done"
233
267
  end
234
268
 
269
+ def git_push
270
+ system "git push" or fail "Couldn't push release"
271
+ end
272
+
235
273
  def increment_version
236
274
  major, minor, patch = PuppetLibrary::VERSION.split(".").map {|n| n.to_i}
237
275
  new_version = "#{major}.#{minor + 1}.0"
data/TODO.yml CHANGED
@@ -1,7 +1,13 @@
1
1
  features:
2
2
  - Web UI:
3
3
  - asynchronous (index page loads too slowly)
4
- - Proxy a git repository
4
+ - Proxy a git repository:
5
+ - make it threadsafe (checkouts into temp dirs)
6
+ - make the specs fast
7
+ - add an integration test
8
+ - make it work with remote forges (clone and fetch on query/download)
9
+ - make it fast (pre-clone repos on startup (maybe just warn if they can't be found). Maybe cache artifacts?)
10
+ - logging
5
11
  - Named subforges:
6
12
  - per-subforge queries
7
13
  - upload modules (web form and API)
@@ -20,6 +20,10 @@ require 'puppet_library/util'
20
20
 
21
21
  module PuppetLibrary::Forge
22
22
 
23
+ # An abstract forge implementation that makes it easier to create new forge
24
+ # types.
25
+ #
26
+ # See PuppetLibrary::Forge::Directory for an example
23
27
  class Abstract
24
28
  def initialize(module_repo)
25
29
  @repo = module_repo
@@ -17,9 +17,14 @@
17
17
 
18
18
  require 'puppet_library/forge/proxy'
19
19
  require 'puppet_library/http/http_client'
20
-
21
20
  module PuppetLibrary::Forge
21
+
22
+ # A forge that proxies a remote forge. All module archives downloaded from the
23
+ # remote forged are cached to disk.
22
24
  class Cache < Proxy
25
+
26
+ # * <tt>:url</tt> - The URL of the remote forge.
27
+ # * <tt>:cache_dir</tt> - The directory in which to cache the downloaded artifacts.
23
28
  def initialize(url, cache_dir, http_client = PuppetLibrary::Http::HttpClient.new)
24
29
  super(url, PuppetLibrary::Http::Cache::InMemory.new, PuppetLibrary::Http::Cache::Disk.new(cache_dir), http_client)
25
30
  end
@@ -19,7 +19,17 @@ require 'puppet_library/forge/abstract'
19
19
  require 'puppet_library/archive/archive_reader'
20
20
 
21
21
  module PuppetLibrary::Forge
22
+
23
+ # A forge that serves modules from a directory on disk.
24
+ #
25
+ # <b>Note:</b>
26
+ # * The modules must be packaged in +.tar.gz+ format
27
+ # * The modules must be named in the format <tt>author-modulename-version.tar.gz</tt>
28
+ # * The modules must contain a +metadata.json+ file
29
+ # That is, the format must be the same as what is produced by <tt>puppet module build</tt>
22
30
  class Directory < PuppetLibrary::Forge::Abstract
31
+
32
+ # * <tt>:module_dir</tt> - The directory containing the packaged modules.
23
33
  def initialize(module_dir)
24
34
  super(self)
25
35
  raise "Module directory '#{module_dir}' doesn't exist" unless File.directory? module_dir
@@ -0,0 +1,106 @@
1
+ # Puppet Library
2
+ # Copyright (C) 2014 drrb
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'json'
18
+ require 'rubygems/package'
19
+ require 'zlib'
20
+ require 'puppet_library/forge/abstract'
21
+
22
+ module PuppetLibrary::Forge
23
+ class GitRepository < PuppetLibrary::Forge::Abstract
24
+ def initialize(author, name, version_tag_regex, git_path)
25
+ super(self)
26
+ @author = author
27
+ @name = name
28
+ @path = File.expand_path(git_path)
29
+ @version_tag_regex = version_tag_regex
30
+ end
31
+
32
+ def get_module(author, name, version)
33
+ unless author == @author && name == @name
34
+ return nil
35
+ end
36
+ unless tags.include? tag_name(version)
37
+ return nil
38
+ end
39
+ on_tag_for(version) do
40
+ PuppetLibrary::Archive::Archiver.archive_dir(@path, "#{@author}-#{@name}-#{version}") do |archive|
41
+ archive.add_file("metadata.json", 0644) do |entry|
42
+ entry.write modulefile.to_metadata.to_json
43
+ end
44
+ end
45
+ end
46
+ end
47
+
48
+ def get_metadata(author, module_name)
49
+ unless author == @author && module_name == @name
50
+ return []
51
+ end
52
+ tags.map do |tag|
53
+ modulefile_for_tag(tag).to_metadata
54
+ end
55
+ end
56
+
57
+ def get_all_metadata
58
+ get_metadata(@author, @name)
59
+ end
60
+
61
+ private
62
+ def tags
63
+ git("tag").split.select {|tag| tag =~ @version_tag_regex }
64
+ end
65
+
66
+ def modulefile_for_tag(tag)
67
+ modulefile_source = git("show refs/tags/#{tag}:Modulefile")
68
+ PuppetLibrary::PuppetModule::Modulefile.parse(modulefile_source)
69
+ end
70
+
71
+ def modulefile
72
+ modulefile_path = File.join(@path, "Modulefile")
73
+ PuppetLibrary::PuppetModule::Modulefile.read(modulefile_path)
74
+ end
75
+
76
+ def package_name(version)
77
+ "#{@author}-#{@name}-#{version}.tar.gz"
78
+ end
79
+
80
+ def tag_name(version)
81
+ version
82
+ end
83
+
84
+ def on_tag_for(version, &block)
85
+ on_tag(tag_name(version), &block)
86
+ end
87
+
88
+ def on_tag(tag, &block)
89
+ git "checkout #{tag}"
90
+ in_dir(@path, &block)
91
+ end
92
+
93
+ def in_dir(dir)
94
+ origin = Dir.pwd
95
+ Dir.chdir dir
96
+ yield
97
+ ensure
98
+ Dir.chdir origin
99
+ end
100
+
101
+ def git(command)
102
+ #TODO: redirection will fail on windows. How do we properly discard stderr?
103
+ IO.popen("git --git-dir=#{@path}/.git --work-tree=#{@path} #{command} 2>/dev/null").read
104
+ end
105
+ end
106
+ end
@@ -18,11 +18,29 @@
18
18
  require 'puppet_library/forge/search_result'
19
19
 
20
20
  module PuppetLibrary::Forge
21
+
22
+ # A forge that delegates to multiple other forges.
23
+ #
24
+ # For queries, all subforges are queried. The results are merged, giving
25
+ # preference to earlier ones. That is, if the same version of a module is
26
+ # found in two different subforges, the one contained in the earlier
27
+ # subforge is kept in the query results.
28
+ #
29
+ # For downloads, subforges are queried sequentially. The first module found
30
+ # is returned.
31
+ #
32
+ # <b>Usage:</b>
33
+ #
34
+ # # A forge that serves modules from disk, and proxies a remote forge
35
+ # multi_forge = Multi.new
36
+ # multi_forge.add_forge(Directory.new("/var/modules"))
37
+ # multi_forge.add_forge(Proxy.new("http://forge.puppetlabs.com"))
21
38
  class Multi
22
39
  def initialize
23
40
  @forges = []
24
41
  end
25
42
 
43
+ # Add another forge to delegate to.
26
44
  def add_forge(forge)
27
45
  @forges << forge
28
46
  end
@@ -20,12 +20,16 @@ require 'puppet_library/http/cache/in_memory'
20
20
  require 'puppet_library/http/cache/noop'
21
21
 
22
22
  module PuppetLibrary::Forge
23
+
24
+ # A forge that proxies a remote forge.
23
25
  class Proxy
26
+
27
+ # * <tt>:url</tt> - The URL of the remote forge.
24
28
  def initialize(url,
25
29
  query_cache = PuppetLibrary::Http::Cache::InMemory.new,
26
30
  download_cache = PuppetLibrary::Http::Cache::NoOp.new,
27
31
  http_client = PuppetLibrary::Http::HttpClient.new)
28
- @url = url
32
+ @url = PuppetLibrary::Http::Url.normalize(url)
29
33
  @http_client = http_client
30
34
  @query_cache = query_cache
31
35
  @download_cache = download_cache
@@ -17,34 +17,36 @@
17
17
 
18
18
  require 'puppet_library/util'
19
19
 
20
- module PuppetLibrary::Forge::SearchResult
21
- def self.merge_by_full_name(results)
22
- results_by_module = results.group_by do |result|
23
- result["full_name"]
20
+ module PuppetLibrary::Forge
21
+ module SearchResult
22
+ def self.merge_by_full_name(results)
23
+ results_by_module = results.group_by do |result|
24
+ result["full_name"]
25
+ end
26
+
27
+ results_by_module.values.map do |module_results|
28
+ combine_search_results(module_results)
29
+ end.flatten
24
30
  end
25
31
 
26
- results_by_module.values.map do |module_results|
27
- combine_search_results(module_results)
28
- end.flatten
29
- end
32
+ def self.combine_search_results(search_results)
33
+ highest_version, tags, releases = search_results.inject([nil, [], []]) do |(highest_version, tags, releases), result|
34
+ [
35
+ max_version(highest_version, result["version"]),
36
+ tags + (result["tag_list"] || []),
37
+ releases + (result["releases"] || [])
38
+ ]
39
+ end
30
40
 
31
- def self.combine_search_results(search_results)
32
- highest_version, tags, releases = search_results.inject([nil, [], []]) do |(highest_version, tags, releases), result|
33
- [
34
- max_version(highest_version, result["version"]),
35
- tags + (result["tag_list"] || []),
36
- releases + (result["releases"] || [])
37
- ]
41
+ combined_result = search_results.first.tap do |result|
42
+ result["version"] = highest_version
43
+ result["tag_list"] = tags.uniq
44
+ result["releases"] = releases.uniq.version_sort_by {|r| r["version"]}.reverse
45
+ end
38
46
  end
39
47
 
40
- combined_result = search_results.first.tap do |result|
41
- result["version"] = highest_version
42
- result["tag_list"] = tags.uniq
43
- result["releases"] = releases.uniq.version_sort_by {|r| r["version"]}.reverse
48
+ def self.max_version(left, right)
49
+ [Gem::Version.new(left), Gem::Version.new(right)].max.version
44
50
  end
45
51
  end
46
-
47
- def self.max_version(left, right)
48
- [Gem::Version.new(left), Gem::Version.new(right)].max.version
49
- end
50
52
  end
@@ -15,12 +15,21 @@
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
16
 
17
17
  require 'puppet_library/archive/archiver'
18
+ require 'puppet_library/forge/abstract'
18
19
  require 'puppet_library/puppet_module/modulefile'
19
20
  require 'json'
20
21
 
21
22
  module PuppetLibrary::Forge
23
+
24
+ # A forge that serves a module from its source on disk.
25
+ # Metadata (+metadata.json+) is generated on the fly.
26
+ #
27
+ # <b>Note:</b>
28
+ # The module directory must have a +Modulefile+.
22
29
  class Source < PuppetLibrary::Forge::Abstract
23
30
  CACHE_TTL_MILLIS = 500
31
+
32
+ # * <tt>:module_dir</tt> - The directory containing the module's source.
24
33
  def initialize(module_dir)
25
34
  super(self)
26
35
  module_dir = File.expand_path(module_dir)
@@ -34,7 +43,7 @@ module PuppetLibrary::Forge
34
43
  return nil unless this_module?(author, name, version)
35
44
  PuppetLibrary::Archive::Archiver.archive_dir(@module_dir, "#{author}-#{name}-#{version}") do |archive|
36
45
  archive.add_file("metadata.json", 0644) do |entry|
37
- entry.write modulefile.to_metadata
46
+ entry.write modulefile.to_metadata.to_json
38
47
  end
39
48
  end
40
49
  end
@@ -22,6 +22,7 @@ module PuppetLibrary::Forge
22
22
  require 'puppet_library/forge/abstract'
23
23
  require 'puppet_library/forge/cache'
24
24
  require 'puppet_library/forge/directory'
25
+ require 'puppet_library/forge/git_repository'
25
26
  require 'puppet_library/forge/multi'
26
27
  require 'puppet_library/forge/proxy'
27
28
  require 'puppet_library/forge/search_result'
@@ -15,39 +15,41 @@
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
- module PuppetLibrary::Http::Cache
19
- class Disk
20
- def initialize(directory)
21
- @directory = directory
22
- end
18
+ module PuppetLibrary::Http
19
+ module Cache
20
+ class Disk
21
+ def initialize(directory)
22
+ @directory = directory
23
+ end
23
24
 
24
- def get(path)
25
- unless include? path
26
- buffer = yield
27
- save(path, buffer)
25
+ def get(path)
26
+ unless include? path
27
+ buffer = yield
28
+ save(path, buffer)
29
+ end
30
+ retrieve(path)
28
31
  end
29
- retrieve(path)
30
- end
31
32
 
32
- private
33
- def include?(path)
34
- File.exist? entry_path(path)
35
- end
33
+ private
34
+ def include?(path)
35
+ File.exist? entry_path(path)
36
+ end
36
37
 
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
38
+ def save(path, buffer)
39
+ file_path = entry_path(path)
40
+ FileUtils.mkdir_p File.dirname(file_path)
41
+ File.open(file_path, "w") do |file|
42
+ file.write buffer.read
43
+ end
42
44
  end
43
- end
44
45
 
45
- def retrieve(path)
46
- File.open(entry_path(path))
47
- end
46
+ def retrieve(path)
47
+ File.open(entry_path(path))
48
+ end
48
49
 
49
- def entry_path(path)
50
- File.join(@directory, path)
50
+ def entry_path(path)
51
+ File.join(@directory, path)
52
+ end
51
53
  end
52
54
  end
53
55
  end
@@ -15,58 +15,60 @@
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
- module PuppetLibrary::Http::Cache
19
- class InMemory
20
- ARBITRARY_CACHE_TTL_MILLIS = 10 * 1000
21
- def initialize(millis_to_live = ARBITRARY_CACHE_TTL_MILLIS)
22
- @reaper = Reaper.new(millis_to_live)
23
- end
24
-
25
- def get(key)
26
- entry = retrieve(key)
27
- if entry
28
- return entry.value unless @reaper.wants_to_kill? entry
18
+ module PuppetLibrary::Http
19
+ module Cache
20
+ class InMemory
21
+ ARBITRARY_CACHE_TTL_MILLIS = 10 * 1000
22
+ def initialize(millis_to_live = ARBITRARY_CACHE_TTL_MILLIS)
23
+ @reaper = Reaper.new(millis_to_live)
29
24
  end
30
25
 
31
- value = yield
32
- save(key, Entry.new(value))
33
- return value
34
- end
35
-
36
- def retrieve(key)
37
- cache[key]
38
- end
39
-
40
- def save(key, entry)
41
- cache[key] = entry
42
- end
26
+ def get(key)
27
+ entry = retrieve(key)
28
+ if entry
29
+ return entry.value unless @reaper.wants_to_kill? entry
30
+ end
43
31
 
44
- private
45
- def cache
46
- @cache ||= {}
47
- end
32
+ value = yield
33
+ save(key, Entry.new(value))
34
+ return value
35
+ end
48
36
 
49
- class Entry
50
- attr_accessor :value
37
+ def retrieve(key)
38
+ cache[key]
39
+ end
51
40
 
52
- def initialize(value)
53
- @birth = Time.now
54
- @value = value
41
+ def save(key, entry)
42
+ cache[key] = entry
55
43
  end
56
44
 
57
- def age_millis
58
- age_seconds = Time.now - @birth
59
- age_seconds * 1000
45
+ private
46
+ def cache
47
+ @cache ||= {}
60
48
  end
61
- end
62
49
 
63
- class Reaper
64
- def initialize(millis_to_live)
65
- @millis_to_live = millis_to_live
50
+ class Entry
51
+ attr_accessor :value
52
+
53
+ def initialize(value)
54
+ @birth = Time.now
55
+ @value = value
56
+ end
57
+
58
+ def age_millis
59
+ age_seconds = Time.now - @birth
60
+ age_seconds * 1000
61
+ end
66
62
  end
67
63
 
68
- def wants_to_kill?(entry)
69
- entry.age_millis > @millis_to_live
64
+ class Reaper
65
+ def initialize(millis_to_live)
66
+ @millis_to_live = millis_to_live
67
+ end
68
+
69
+ def wants_to_kill?(entry)
70
+ entry.age_millis > @millis_to_live
71
+ end
70
72
  end
71
73
  end
72
74
  end
@@ -17,10 +17,12 @@
17
17
 
18
18
  require 'puppet_library/http/cache/in_memory'
19
19
 
20
- module PuppetLibrary::Http::Cache
21
- class NoOp
22
- def get(path)
23
- yield
20
+ module PuppetLibrary::Http
21
+ module Cache
22
+ class NoOp
23
+ def get(path)
24
+ yield
25
+ end
24
26
  end
25
27
  end
26
28
  end
@@ -15,8 +15,10 @@
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
- module PuppetLibrary::Http::Cache
19
- require 'puppet_library/http/cache/disk'
20
- require 'puppet_library/http/cache/in_memory'
21
- require 'puppet_library/http/cache/noop'
18
+ module PuppetLibrary::Http
19
+ module Cache
20
+ require 'puppet_library/http/cache/disk'
21
+ require 'puppet_library/http/cache/in_memory'
22
+ require 'puppet_library/http/cache/noop'
23
+ end
22
24
  end
@@ -17,8 +17,12 @@
17
17
  module PuppetLibrary::PuppetModule
18
18
  class Modulefile
19
19
  def self.read(modulefile_path)
20
+ parse(File.read(modulefile_path))
21
+ end
22
+
23
+ def self.parse(modulefile_source)
20
24
  Modulefile.new.tap do |modulefile|
21
- modulefile.instance_eval(File.read(modulefile_path))
25
+ modulefile.instance_eval(modulefile_source)
22
26
  end
23
27
  end
24
28
 
@@ -21,6 +21,19 @@ require 'haml'
21
21
  require 'puppet_library/forge/multi'
22
22
 
23
23
  module PuppetLibrary
24
+ # The Puppet Library server
25
+ #
26
+ # A Rack application that can be configured as follows:
27
+ #
28
+ # server = PuppetLibrary::Server.set_up do |library|
29
+ # # Look for my modules locally
30
+ # library.forge PuppetLibrary::Forge::Directory.new("/var/lib/modules")
31
+ #
32
+ # # Get everything else from the Puppet Forge
33
+ # library.forge PuppetLibrary::Forge::Proxy.new("http://forge.puppetlabs.com")
34
+ # end
35
+ #
36
+ # run server
24
37
  class Server < Sinatra::Base
25
38
  class Config
26
39
  def initialize(forge)
@@ -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.9.0"
19
+ VERSION = "0.9.1"
20
20
  end
@@ -0,0 +1,125 @@
1
+ # Puppet Library
2
+ # Copyright (C) 2014 drrb
3
+ #
4
+ # This program is free software: you can redistribute it and/or modify
5
+ # it under the terms of the GNU General Public License as published by
6
+ # the Free Software Foundation, either version 3 of the License, or
7
+ # (at your option) any later version.
8
+ #
9
+ # This program is distributed in the hope that it will be useful,
10
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
11
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
+ # GNU General Public License for more details.
13
+ #
14
+ # You should have received a copy of the GNU General Public License
15
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'spec_helper'
18
+
19
+ module PuppetLibrary::Forge
20
+ describe GitRepository do
21
+ @@repo_path = Tempdir.create("git-repo")
22
+ @@versions = [ "0.9.0", "1.0.0-rc1", "1.0.0" ]
23
+ @@tags = @@versions + [ "xxx" ]
24
+
25
+ before :all do
26
+ def git(command)
27
+ git_command = "git --git-dir=#{@@repo_path}/.git --work-tree=#{@@repo_path} #{command}"
28
+ `#{git_command}`
29
+ unless $?.success?
30
+ raise "Failed to run command: \"#{git_command}\""
31
+ end
32
+ end
33
+
34
+ git "init"
35
+ git "config user.name tester"
36
+ git "config user.email tester@example.com"
37
+ @@versions.zip(@@tags).each do |(version, tag)|
38
+ File.open(File.join(@@repo_path, "Modulefile"), "w") do |modulefile|
39
+ modulefile.write <<-MODULEFILE
40
+ name 'puppetlabs-apache'
41
+ version '#{version}'
42
+ author 'puppetlabs'
43
+ MODULEFILE
44
+ end
45
+ git "add ."
46
+ git "commit --message='Version #{version}'"
47
+ git "tag #{tag}"
48
+ end
49
+ end
50
+
51
+ after :all do
52
+ rm_rf @@repo_path
53
+ end
54
+
55
+ let(:forge) { GitRepository.new("puppetlabs", "apache", /[0-9.]+/, @@repo_path) }
56
+
57
+ describe "#get_module" do
58
+ context "when the requested author is different from the configured author" do
59
+ it "returns nil" do
60
+ buffer = forge.get_module("dodgybrothers", "apache", "1.0.0")
61
+ expect(buffer).to be_nil
62
+ end
63
+ end
64
+
65
+ context "when the requested module name is different from the configured name" do
66
+ it "returns nil" do
67
+ buffer = forge.get_module("puppetlabs", "stdlib", "1.0.0")
68
+ expect(buffer).to be_nil
69
+ end
70
+ end
71
+
72
+ context "when the tag for the requested version doesn't exist" do
73
+ it "returns nil" do
74
+ buffer = forge.get_module("puppetlabs", "apache", "9.9.9")
75
+ expect(buffer).to be_nil
76
+ end
77
+ end
78
+
79
+ context "when the module is requested" do
80
+ it "returns an archive of the module" do
81
+ buffer = forge.get_module("puppetlabs", "apache", "1.0.0")
82
+ expect(buffer).to be_tgz_with "puppetlabs-apache-1.0.0/Modulefile", /version '1.0.0'/
83
+ end
84
+ it "generates the metadata file and includes it in the archive" do
85
+ buffer = forge.get_module("puppetlabs", "apache", "1.0.0")
86
+ expect(buffer).to be_tgz_with "puppetlabs-apache-1.0.0/metadata.json", /"version":"1.0.0"/
87
+ end
88
+ end
89
+ end
90
+
91
+ describe "#get_metadata" do
92
+ context "when the requested author is different from the configured author" do
93
+ it "returns nil" do
94
+ metadata = forge.get_metadata("dodgybrothers", "apache")
95
+ expect(metadata).to be_empty
96
+ end
97
+ end
98
+
99
+ context "when the requested module name is different from the configured name" do
100
+ it "returns an empty array" do
101
+ metadata = forge.get_metadata("puppetlabs", "stdlib")
102
+ expect(metadata).to be_empty
103
+ end
104
+ end
105
+
106
+ context "when the module is requested" do
107
+ it "generates the metadata for the each version" do
108
+ metadata = forge.get_metadata("puppetlabs", "apache")
109
+ expect(metadata).to have(3).versions
110
+ expect(metadata.first["name"]).to eq "puppetlabs-apache"
111
+ expect(metadata.first["version"]).to eq "0.9.0"
112
+ end
113
+ end
114
+ end
115
+
116
+ describe "#get_all_metadata" do
117
+ it "generates the metadata for the each version" do
118
+ metadata = forge.get_metadata("puppetlabs", "apache")
119
+ expect(metadata).to have(3).versions
120
+ expect(metadata.first["name"]).to eq "puppetlabs-apache"
121
+ expect(metadata.first["version"]).to eq "0.9.0"
122
+ end
123
+ end
124
+ end
125
+ end
@@ -95,7 +95,7 @@ module PuppetLibrary::Forge
95
95
  it "generates a metadata file in the packaged application" do
96
96
  buffer = forge.get_module("puppetlabs", "apache", "1.0.0")
97
97
 
98
- expect(buffer).to be_tgz_with(/metadata.json/, /puppetlabs-apache/)
98
+ expect(buffer).to be_tgz_with(/metadata.json/, /"name":"puppetlabs-apache"/)
99
99
  end
100
100
  end
101
101
  end
@@ -101,6 +101,13 @@ module PuppetLibrary::PuppetModule
101
101
  end
102
102
  end
103
103
  end
104
+
105
+ describe "#parse" do
106
+ it "works like #read, but with a string" do
107
+ metadata = Modulefile.parse("version '1.0.0'")
108
+ expect(metadata.get_version).to eq "1.0.0"
109
+ end
110
+ end
104
111
  end
105
112
  end
106
113
 
metadata CHANGED
@@ -1,303 +1,149 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: puppet-library
3
- version: !ruby/object:Gem::Version
4
- version: 0.9.0
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.1
5
5
  platform: ruby
6
- authors:
6
+ authors:
7
7
  - drrb
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-15 00:00:00.000000000 Z
12
- dependencies:
13
- - !ruby/object:Gem::Dependency
11
+
12
+ date: 2014-02-20 00:00:00 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
14
15
  name: sinatra
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - '>='
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
16
+ version_requirements: &id001 !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - &id002
19
+ - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: "0"
21
22
  prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - '>='
25
- - !ruby/object:Gem::Version
26
- version: '0'
27
- - !ruby/object:Gem::Dependency
28
- name: json
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - '>='
32
- - !ruby/object:Gem::Version
33
- version: '0'
23
+ requirement: *id001
34
24
  type: :runtime
25
+ - !ruby/object:Gem::Dependency
26
+ name: json
27
+ version_requirements: &id003 !ruby/object:Gem::Requirement
28
+ requirements:
29
+ - *id002
35
30
  prerelease: false
36
- version_requirements: !ruby/object:Gem::Requirement
37
- requirements:
38
- - - '>='
39
- - !ruby/object:Gem::Version
40
- version: '0'
41
- - !ruby/object:Gem::Dependency
42
- name: haml
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - '>='
46
- - !ruby/object:Gem::Version
47
- version: '0'
31
+ requirement: *id003
48
32
  type: :runtime
33
+ - !ruby/object:Gem::Dependency
34
+ name: haml
35
+ version_requirements: &id004 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - *id002
49
38
  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
39
+ requirement: *id004
40
+ type: :runtime
41
+ - !ruby/object:Gem::Dependency
56
42
  name: bundler
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
43
+ version_requirements: &id005 !ruby/object:Gem::Requirement
44
+ requirements:
59
45
  - - ~>
60
- - !ruby/object:Gem::Version
61
- version: '1.3'
62
- type: :development
46
+ - !ruby/object:Gem::Version
47
+ version: "1.3"
63
48
  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: coveralls
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - '>='
74
- - !ruby/object:Gem::Version
75
- version: '0'
49
+ requirement: *id005
76
50
  type: :development
51
+ - !ruby/object:Gem::Dependency
52
+ name: coveralls
53
+ version_requirements: &id006 !ruby/object:Gem::Requirement
54
+ requirements:
55
+ - *id002
77
56
  prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - '>='
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: gitsu
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - '>='
88
- - !ruby/object:Gem::Version
89
- version: '0'
57
+ requirement: *id006
90
58
  type: :development
59
+ - !ruby/object:Gem::Dependency
60
+ name: gitsu
61
+ version_requirements: &id007 !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - *id002
91
64
  prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - '>='
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
65
+ requirement: *id007
66
+ type: :development
67
+ - !ruby/object:Gem::Dependency
98
68
  name: librarian-puppet
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - '='
102
- - !ruby/object:Gem::Version
69
+ version_requirements: &id008 !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - "="
72
+ - !ruby/object:Gem::Version
103
73
  version: 0.9.10
104
- type: :development
105
74
  prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - '='
109
- - !ruby/object:Gem::Version
110
- version: 0.9.10
111
- - !ruby/object:Gem::Dependency
75
+ requirement: *id008
76
+ type: :development
77
+ - !ruby/object:Gem::Dependency
112
78
  name: mime-types
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
79
+ version_requirements: &id009 !ruby/object:Gem::Requirement
80
+ requirements:
115
81
  - - <
116
- - !ruby/object:Gem::Version
117
- version: '2'
118
- type: :development
82
+ - !ruby/object:Gem::Version
83
+ version: "2"
119
84
  prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - <
123
- - !ruby/object:Gem::Version
124
- version: '2'
125
- - !ruby/object:Gem::Dependency
126
- name: pry
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - '>='
130
- - !ruby/object:Gem::Version
131
- version: '0'
85
+ requirement: *id009
132
86
  type: :development
87
+ - !ruby/object:Gem::Dependency
88
+ name: pry
89
+ version_requirements: &id010 !ruby/object:Gem::Requirement
90
+ requirements:
91
+ - *id002
133
92
  prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - '>='
137
- - !ruby/object:Gem::Version
138
- version: '0'
139
- - !ruby/object:Gem::Dependency
140
- name: puppet
141
- requirement: !ruby/object:Gem::Requirement
142
- requirements:
143
- - - ~>
144
- - !ruby/object:Gem::Version
145
- version: 3.3.0
93
+ requirement: *id010
146
94
  type: :development
147
- prerelease: false
148
- version_requirements: !ruby/object:Gem::Requirement
149
- requirements:
95
+ - !ruby/object:Gem::Dependency
96
+ name: puppet
97
+ version_requirements: &id011 !ruby/object:Gem::Requirement
98
+ requirements:
150
99
  - - ~>
151
- - !ruby/object:Gem::Version
100
+ - !ruby/object:Gem::Version
152
101
  version: 3.3.0
153
- - !ruby/object:Gem::Dependency
154
- name: rack-test
155
- requirement: !ruby/object:Gem::Requirement
156
- requirements:
157
- - - '>='
158
- - !ruby/object:Gem::Version
159
- version: '0'
160
- type: :development
161
102
  prerelease: false
162
- version_requirements: !ruby/object:Gem::Requirement
163
- requirements:
164
- - - '>='
165
- - !ruby/object:Gem::Version
166
- version: '0'
167
- - !ruby/object:Gem::Dependency
168
- name: rake
169
- requirement: !ruby/object:Gem::Requirement
170
- requirements:
171
- - - '>='
172
- - !ruby/object:Gem::Version
173
- version: '0'
174
- type: :development
175
- prerelease: false
176
- version_requirements: !ruby/object:Gem::Requirement
177
- requirements:
178
- - - '>='
179
- - !ruby/object:Gem::Version
180
- version: '0'
181
- - !ruby/object:Gem::Dependency
182
- name: rspec
183
- requirement: !ruby/object:Gem::Requirement
184
- requirements:
185
- - - '>='
186
- - !ruby/object:Gem::Version
187
- version: '0'
188
- type: :development
189
- prerelease: false
190
- version_requirements: !ruby/object:Gem::Requirement
191
- requirements:
192
- - - '>='
193
- - !ruby/object:Gem::Version
194
- version: '0'
195
- - !ruby/object:Gem::Dependency
196
- name: simplecov
197
- requirement: !ruby/object:Gem::Requirement
198
- requirements:
199
- - - '>='
200
- - !ruby/object:Gem::Version
201
- version: '0'
202
- type: :development
203
- prerelease: false
204
- version_requirements: !ruby/object:Gem::Requirement
205
- requirements:
206
- - - '>='
207
- - !ruby/object:Gem::Version
208
- version: '0'
209
- - !ruby/object:Gem::Dependency
210
- name: guard
211
- requirement: !ruby/object:Gem::Requirement
212
- requirements:
213
- - - '>='
214
- - !ruby/object:Gem::Version
215
- version: '0'
216
- type: :development
217
- prerelease: false
218
- version_requirements: !ruby/object:Gem::Requirement
219
- requirements:
220
- - - '>='
221
- - !ruby/object:Gem::Version
222
- version: '0'
223
- - !ruby/object:Gem::Dependency
224
- name: guard-rspec
225
- requirement: !ruby/object:Gem::Requirement
226
- requirements:
227
- - - '>='
228
- - !ruby/object:Gem::Version
229
- version: '0'
103
+ requirement: *id011
230
104
  type: :development
105
+ - !ruby/object:Gem::Dependency
106
+ name: rack-test
107
+ version_requirements: &id012 !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - *id002
231
110
  prerelease: false
232
- version_requirements: !ruby/object:Gem::Requirement
233
- requirements:
234
- - - '>='
235
- - !ruby/object:Gem::Version
236
- version: '0'
237
- - !ruby/object:Gem::Dependency
238
- name: terminal-notifier-guard
239
- requirement: !ruby/object:Gem::Requirement
240
- requirements:
241
- - - '>='
242
- - !ruby/object:Gem::Version
243
- version: '0'
111
+ requirement: *id012
244
112
  type: :development
113
+ - !ruby/object:Gem::Dependency
114
+ name: rake
115
+ version_requirements: &id013 !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - *id002
245
118
  prerelease: false
246
- version_requirements: !ruby/object:Gem::Requirement
247
- requirements:
248
- - - '>='
249
- - !ruby/object:Gem::Version
250
- version: '0'
251
- - !ruby/object:Gem::Dependency
252
- name: capybara
253
- requirement: !ruby/object:Gem::Requirement
254
- requirements:
255
- - - '>='
256
- - !ruby/object:Gem::Version
257
- version: '0'
119
+ requirement: *id013
258
120
  type: :development
121
+ - !ruby/object:Gem::Dependency
122
+ name: rspec
123
+ version_requirements: &id014 !ruby/object:Gem::Requirement
124
+ requirements:
125
+ - *id002
259
126
  prerelease: false
260
- version_requirements: !ruby/object:Gem::Requirement
261
- requirements:
262
- - - '>='
263
- - !ruby/object:Gem::Version
264
- version: '0'
265
- - !ruby/object:Gem::Dependency
266
- name: nokogiri
267
- requirement: !ruby/object:Gem::Requirement
268
- requirements:
269
- - - '>='
270
- - !ruby/object:Gem::Version
271
- version: '0'
127
+ requirement: *id014
272
128
  type: :development
129
+ - !ruby/object:Gem::Dependency
130
+ name: simplecov
131
+ version_requirements: &id015 !ruby/object:Gem::Requirement
132
+ requirements:
133
+ - *id002
273
134
  prerelease: false
274
- version_requirements: !ruby/object:Gem::Requirement
275
- requirements:
276
- - - '>='
277
- - !ruby/object:Gem::Version
278
- version: '0'
279
- - !ruby/object:Gem::Dependency
280
- name: cucumber
281
- requirement: !ruby/object:Gem::Requirement
282
- requirements:
283
- - - '>='
284
- - !ruby/object:Gem::Version
285
- version: '0'
135
+ requirement: *id015
286
136
  type: :development
287
- prerelease: false
288
- version_requirements: !ruby/object:Gem::Requirement
289
- requirements:
290
- - - '>='
291
- - !ruby/object:Gem::Version
292
- version: '0'
293
137
  description: A private Puppet forge
294
- email:
138
+ email:
295
139
  - drrrrrrrrrrrb@gmail.com
296
- executables:
140
+ executables:
297
141
  - puppet-library
298
142
  extensions: []
143
+
299
144
  extra_rdoc_files: []
300
- files:
145
+
146
+ files:
301
147
  - .gitignore
302
148
  - .licenseignore
303
149
  - .simplecov
@@ -328,6 +174,7 @@ files:
328
174
  - lib/puppet_library/forge/abstract.rb
329
175
  - lib/puppet_library/forge/cache.rb
330
176
  - lib/puppet_library/forge/directory.rb
177
+ - lib/puppet_library/forge/git_repository.rb
331
178
  - lib/puppet_library/forge/multi.rb
332
179
  - lib/puppet_library/forge/proxy.rb
333
180
  - lib/puppet_library/forge/search_result.rb
@@ -351,6 +198,7 @@ files:
351
198
  - spec/forge/abstract_spec.rb
352
199
  - spec/forge/cache_spec.rb
353
200
  - spec/forge/directory_spec.rb
201
+ - spec/forge/git_repository_spec.rb
354
202
  - spec/forge/multi_spec.rb
355
203
  - spec/forge/proxy_spec.rb
356
204
  - spec/forge/source_spec.rb
@@ -367,30 +215,29 @@ files:
367
215
  - spec/util_spec.rb
368
216
  - test/librarian_puppet_integration_test.rb
369
217
  homepage: https://github.com/drrb/puppet-library
370
- licenses:
218
+ licenses:
371
219
  - GPL-3
372
220
  metadata: {}
221
+
373
222
  post_install_message:
374
223
  rdoc_options: []
375
- require_paths:
224
+
225
+ require_paths:
376
226
  - lib
377
- required_ruby_version: !ruby/object:Gem::Requirement
378
- requirements:
379
- - - '>='
380
- - !ruby/object:Gem::Version
381
- version: '0'
382
- required_rubygems_version: !ruby/object:Gem::Requirement
383
- requirements:
384
- - - '>='
385
- - !ruby/object:Gem::Version
386
- version: '0'
227
+ required_ruby_version: !ruby/object:Gem::Requirement
228
+ requirements:
229
+ - *id002
230
+ required_rubygems_version: !ruby/object:Gem::Requirement
231
+ requirements:
232
+ - *id002
387
233
  requirements: []
234
+
388
235
  rubyforge_project:
389
- rubygems_version: 2.0.3
236
+ rubygems_version: 2.0.14
390
237
  signing_key:
391
238
  specification_version: 4
392
239
  summary: Puppet Library is a private Puppet module server that's compatible with librarian-puppet.
393
- test_files:
240
+ test_files:
394
241
  - features/module_list.feature
395
242
  - features/module_page.feature
396
243
  - features/module_search.feature
@@ -401,6 +248,7 @@ test_files:
401
248
  - spec/forge/abstract_spec.rb
402
249
  - spec/forge/cache_spec.rb
403
250
  - spec/forge/directory_spec.rb
251
+ - spec/forge/git_repository_spec.rb
404
252
  - spec/forge/multi_spec.rb
405
253
  - spec/forge/proxy_spec.rb
406
254
  - spec/forge/source_spec.rb