puppet-library 0.9.0 → 0.9.1

Sign up to get free protection for your applications and to get access to all the features.
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