puppet-library 0.0.1 → 0.0.2

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
1
  ---
2
2
  SHA1:
3
- metadata.gz: 1d87d552d8e6d73a785d1619b51b13a5945c2895
4
- data.tar.gz: 74aebbf4aaa5fcbbd38be6305196871622af6c79
3
+ metadata.gz: 038f863a597766d136e7db4d8f71245844334d7c
4
+ data.tar.gz: 0f98e71f5110f3875d4c03a401446bf400faa0bc
5
5
  SHA512:
6
- metadata.gz: 80b23c9e84ceb508d0fb04978f107848a1bcaf499f8f094e82e9cca9b7fac7a6d18c79dfa952508db5e59c8bd2a86ffed20aec69cc094743adca2d8154a82d8d
7
- data.tar.gz: 599abb2bb5d26aa47060f2fe43b7138893343ffbfc2ccc4aa3ff4476e2d1ce70cb745dc88b9a9a500e1287d54967a5a1e78a123747d76ce744babb970a7eacf0
6
+ metadata.gz: 210fbe7f939854063796aacf44bcdd00da819f3ce97ede62ed58d00ad8c7cd787630aba645bbd460064a5f142da86613b65c920f7995bade1ded406fa049d6b6
7
+ data.tar.gz: 4978484237188df4973d38aa8880dbfe3829d17753714f8f20cbb29bf85fbbb6426facb137fb71aefe4125e34dcf690142adf45747c5bffc869009abdb825458
data/.licenseignore CHANGED
@@ -1 +1,2 @@
1
1
  .gitignore
2
+ TODO.yml
data/Rakefile CHANGED
@@ -48,3 +48,15 @@ task "version" do
48
48
  puts PuppetLibrary::VERSION
49
49
  end
50
50
 
51
+ desc "Release Puppet Library"
52
+ task "push-release" => ["check-license", :verify] do
53
+ puts "Releasing #{PuppetLibrary::VERSION}"
54
+ Rake::Task[:release].invoke
55
+
56
+ major, minor, patch = PuppetLibrary::VERSION.split(".").map {|n| n.to_i}
57
+ new_version = "#{major}.#{minor + 1}.0"
58
+ puts "Updating version number to #{new_version}"
59
+ system(%q[sed -i '' -E 's/VERSION = ".*"/VERSION = "] + new_version + %q["/' lib/puppet_library/version.rb]) or fail "Couldn't update version"
60
+ PuppetLibrary::VERSION.replace new_version
61
+ system "git commit lib/puppet_library/version.rb --message='[release] Incremented version number'" or fail "Couldn't commit new version number"
62
+ end
data/TODO.yml ADDED
@@ -0,0 +1,5 @@
1
+ Features:
2
+ - Configure embedded server (currently uses the default Rack server)
3
+ - Proxy another repository
4
+ - Use config from a config file
5
+ - Document usage with Passenger
data/bin/puppet-library CHANGED
@@ -22,37 +22,5 @@ require "puppet_library"
22
22
  require 'optparse'
23
23
 
24
24
  module PuppetLibrary
25
- options = {}
26
- OptionParser.new do |opts|
27
- opts.banner = "Usage: #{File.basename $0} [options]"
28
-
29
- options[:port] = "9292"
30
- opts.on("-p", "--port [PORT]", "Port to listen on (defaults to #{options[:port]}") do |port|
31
- options[:port] = port
32
- end
33
-
34
- options[:hostname] = "0.0.0.0"
35
- opts.on("-b", "--bind-host [HOSTNAME]", "Host name to bind to (defaults to #{options[:hostname]}") do |hostname|
36
- options[:hostname] = hostname
37
- end
38
-
39
- options[:module_dir] = "./modules"
40
- opts.on("-m", "--module-dir [DIR]", "Directory containing the modules (defaults to #{options[:module_dir]})") do |module_dir|
41
- options[:module_dir] = module_dir
42
- end
43
- end.parse!
44
-
45
- server = Server.new(ModuleRepo.new(options[:module_dir]))
46
-
47
- dispatch = Rack::Builder.app do
48
- map '/' do
49
- run Server.new
50
- end
51
- end
52
-
53
- Rack::Server.start({
54
- app: dispatch,
55
- Host: options[:hostname],
56
- Port: options[:port]
57
- })
25
+ PuppetLibrary.new.go(ARGV)
58
26
  end
data/config.ru CHANGED
@@ -15,6 +15,8 @@
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 'rubygems'
18
19
  require 'puppet_library'
19
20
 
21
+ PuppetLibrary::Server.set :module_repo, ModuleRepo::Directory.new("/var/puppet-library/modules")
20
22
  run PuppetLibrary::Server
@@ -15,5 +15,11 @@
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 "puppet_library/server"
19
- require "puppet_library/version"
18
+ require 'puppet_library/version'
19
+
20
+ require 'puppet_library/puppet_library'
21
+ require 'puppet_library/server'
22
+ require 'puppet_library/module_metadata'
23
+ require 'puppet_library/module_repo/directory'
24
+ require 'puppet_library/module_repo/multi'
25
+ require 'puppet_library/util'
@@ -0,0 +1,67 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2013 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
19
+ class ModuleMetadata
20
+
21
+ def initialize(metadata)
22
+ @metadata = metadata
23
+ end
24
+
25
+ def author
26
+ @metadata["name"][/^[^-]+/]
27
+ end
28
+
29
+ def name
30
+ @metadata["name"].sub(/^[^-]+-/, "")
31
+ end
32
+
33
+ def full_name
34
+ @metadata["name"].sub("-", "/")
35
+ end
36
+
37
+ def version
38
+ @metadata["version"]
39
+ end
40
+
41
+ def dependencies
42
+ @metadata["dependencies"]
43
+ end
44
+
45
+ def dependency_names
46
+ dependencies.map {|d| d["name"]}
47
+ end
48
+
49
+ def to_info
50
+ {
51
+ "author" => author,
52
+ "full_name" => full_name,
53
+ "name" => name,
54
+ "desc" => @metadata["description"],
55
+ "releases" => [ { "version" => version } ]
56
+ }
57
+ end
58
+
59
+ def to_version
60
+ {
61
+ "file" => "/modules/#{author}-#{name}-#{version}.tar.gz",
62
+ "version" => version,
63
+ "dependencies" => dependencies.map {|m| [ m["name"], m["version_requirement"] ]}
64
+ }
65
+ end
66
+ end
67
+ end
@@ -13,11 +13,13 @@
13
13
  #
14
14
  # You should have received a copy of the GNU General Public License
15
15
  # along with this program. If not, see <http://www.gnu.org/licenses/>.
16
+
17
+ require 'json'
16
18
  require 'rubygems/package'
17
19
  require 'zlib'
18
20
 
19
- module PuppetLibrary
20
- class ModuleRepo
21
+ module PuppetLibrary::ModuleRepo
22
+ class Directory
21
23
  def initialize(module_dir)
22
24
  @module_dir = module_dir
23
25
  end
@@ -0,0 +1,43 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2013 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::ModuleRepo
19
+ class Multi
20
+ def repos
21
+ @repos ||= []
22
+ end
23
+
24
+ def add_repo(repo)
25
+ repos << repo
26
+ end
27
+
28
+ def get_module(author, name, version)
29
+ repos.each do |repo|
30
+ mod = repo.get_module(author, name, version)
31
+ return mod unless mod.nil?
32
+ end
33
+ return nil
34
+ end
35
+
36
+ def get_metadata(author, name)
37
+ metadata_list = repos.inject([]) do |metadata_list, repo|
38
+ metadata_list + repo.get_metadata(author, name)
39
+ end
40
+ metadata_list.unique_by { |metadata| metadata["version"] }
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,102 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2013 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 'rack'
19
+ require 'puppet_library/module_repo/directory'
20
+ require 'puppet_library/module_repo/multi'
21
+
22
+ module PuppetLibrary
23
+ class PuppetLibrary
24
+ def initialize(log = STDERR)
25
+ @log = log
26
+ end
27
+
28
+ def go(args)
29
+ options = parse_options(args)
30
+ server = build_server(options)
31
+ announce_server_start(options)
32
+
33
+ start_server(server, options)
34
+ rescue ExpectedError => error
35
+ @log.puts "Error: #{error}"
36
+ end
37
+
38
+ private
39
+ def parse_options(args)
40
+ options = {}
41
+ option_parser = OptionParser.new do |opts|
42
+ opts.banner = "Usage: #{File.basename $0} [options]"
43
+
44
+ options[:port] = "9292"
45
+ opts.on("-p", "--port [PORT]", "Port to listen on (defaults to #{options[:port]})") do |port|
46
+ options[:port] = port
47
+ end
48
+
49
+ options[:hostname] = "0.0.0.0"
50
+ opts.on("-b", "--bind-host [HOSTNAME]", "Host name to bind to (defaults to #{options[:hostname]})") do |hostname|
51
+ options[:hostname] = hostname
52
+ end
53
+
54
+ options[:module_dirs] = []
55
+ opts.on("-m", "--module-dir [DIR]", "Directory containing the modules (can be specified multiple times. Defaults to './modules')") do |module_dir|
56
+ options[:module_dirs] << module_dir
57
+ end
58
+ end
59
+ begin
60
+ option_parser.parse(args)
61
+ rescue OptionParser::InvalidOption => parse_error
62
+ raise ExpectedError, parse_error.message + "\n" + option_parser.help
63
+ end
64
+
65
+ if options[:module_dirs].empty?
66
+ options[:module_dirs] << "./modules"
67
+ end
68
+
69
+ return options
70
+ end
71
+
72
+ def build_server(options)
73
+ module_repo = ModuleRepo::Multi.new
74
+ options[:module_dirs].each do |dir|
75
+ subrepo = ModuleRepo::Directory.new(dir)
76
+ module_repo.add_repo(subrepo)
77
+ end
78
+ Server.new(module_repo)
79
+ end
80
+
81
+ def announce_server_start(options)
82
+ @log.puts "Starting Puppet Library server:"
83
+ @log.puts " |- Port: #{options[:port]}"
84
+ @log.puts " |- Host: #{options[:hostname]}"
85
+ @log.puts " `- Module dirs:"
86
+ options[:module_dirs].each do |dir|
87
+ @log.puts " - #{dir}"
88
+ end
89
+ end
90
+
91
+ def start_server(server, options)
92
+ Rack::Server.start(
93
+ :app => server,
94
+ :Host => options[:hostname],
95
+ :Port => options[:port]
96
+ )
97
+ end
98
+ end
99
+
100
+ class ExpectedError < StandardError
101
+ end
102
+ end
@@ -14,10 +14,19 @@
14
14
  #
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 'sinatra/base'
18
- require 'json'
19
19
 
20
- require 'puppet_library/module_repo'
20
+ require 'puppet_library/module_metadata'
21
+ require 'puppet_library/module_repo/multi'
22
+
23
+ class Array
24
+ def deep_merge
25
+ inject({}) do |merged, map|
26
+ merged.deep_merge(map)
27
+ end
28
+ end
29
+ end
21
30
 
22
31
  class Hash
23
32
  def deep_merge(other)
@@ -32,61 +41,11 @@ class Hash
32
41
  end
33
42
 
34
43
  module PuppetLibrary
35
-
36
- class ModuleMetadata
37
-
38
- def initialize(metadata)
39
- @metadata = metadata
40
- end
41
-
42
- def author
43
- @metadata["name"][/^[^-]+/]
44
- end
45
-
46
- def name
47
- @metadata["name"].sub(/^[^-]+-/, "")
48
- end
49
-
50
- def full_name
51
- @metadata["name"].sub("-", "/")
52
- end
53
-
54
- def version
55
- @metadata["version"]
56
- end
57
-
58
- def dependencies
59
- @metadata["dependencies"]
60
- end
61
-
62
- def dependency_names
63
- dependencies.map {|d| d["name"]}
64
- end
65
-
66
- def to_info
67
- {
68
- "author" => author,
69
- "full_name" => full_name,
70
- "name" => name,
71
- "desc" => @metadata["description"],
72
- "releases" => [ { "version" => version } ]
73
- }
74
- end
75
-
76
- def to_version
77
- {
78
- "file" => "/modules/#{author}-#{name}-#{version}.tar.gz",
79
- "version" => version,
80
- "dependencies" => dependencies.map {|m| [ m["name"], m["version_requirement"] ]}
81
- }
82
- end
83
- end
84
-
85
44
  class Server < Sinatra::Base
86
45
 
87
- def initialize(module_repo = ModuleRepo.new("modules"))
46
+ def initialize(module_repo = ModuleRepo::Multi.new)
88
47
  super(nil)
89
- @repo = module_repo
48
+ @repo = settings.respond_to?(:module_repo) ? settings.module_repo : module_repo
90
49
  end
91
50
 
92
51
  configure do
@@ -96,37 +55,22 @@ module PuppetLibrary
96
55
  get "/:author/:module.json" do
97
56
  author = params[:author]
98
57
  module_name = params[:module]
99
- modules = get_metadata(author, module_name)
100
- if modules.empty?
58
+
59
+ begin
60
+ get_module_metadata(author, module_name).to_json
61
+ rescue ModuleNotFound
101
62
  status 410
102
63
  {"error" => "Could not find module \"#{module_name}\""}.to_json
103
- else
104
- modules.map do |metadata|
105
- metadata.to_info
106
- end.inject({}) do |merged, map|
107
- merged.deep_merge(map)
108
- end.to_json
109
64
  end
110
65
  end
111
66
 
112
67
  get "/api/v1/releases.json" do
113
- full_name = params[:module]
114
- module_queue = [full_name]
115
- modules_versions = {}
116
- while module_full_name = module_queue.shift
117
- next if modules_versions[module_full_name]
118
- author, module_name = module_full_name.split "/"
119
- module_versions = get_metadata(author, module_name)
120
- dependencies = module_versions.map {|v| v.dependency_names }.flatten
121
- module_queue += dependencies
122
- modules_versions[module_full_name] = module_versions.map { |v| v.to_version }
123
- end
124
-
125
- if modules_versions.values == [[]]
68
+ author, module_name = params[:module].split "/"
69
+ begin
70
+ get_module_metadata_with_dependencies(author, module_name).to_json
71
+ rescue ModuleNotFound
126
72
  status 410
127
- {"error" => "Module #{full_name} not found"}.to_json
128
- else
129
- modules_versions.to_json
73
+ {"error" => "Module #{author}/#{module_name} not found"}.to_json
130
74
  end
131
75
  end
132
76
 
@@ -134,18 +78,57 @@ module PuppetLibrary
134
78
  author = params[:author]
135
79
  name = params[:module]
136
80
  version = params[:version]
137
- buffer = @repo.get_module(author, name, version)
81
+
138
82
  content_type "application/octet-stream"
139
- if buffer.nil?
83
+
84
+ begin
85
+ get_module_buffer(author, name, version).tap do
86
+ attachment "#{author}-#{name}-#{version}.tar.gz"
87
+ end
88
+ rescue ModuleNotFound
140
89
  status 404
141
- else
142
- attachment "#{author}-#{name}-#{version}.tar.gz"
143
- buffer
144
90
  end
145
91
  end
146
92
 
93
+ private
94
+ def get_module_metadata(author, name)
95
+ modules = get_metadata(author, name)
96
+ raise ModuleNotFound if modules.empty?
97
+
98
+ module_infos = modules.map { |m| m.to_info }
99
+ module_infos.deep_merge
100
+ end
101
+
102
+ def get_module_metadata_with_dependencies(author, name)
103
+ full_name = "#{author}/#{name}"
104
+
105
+ module_queue = []
106
+ modules_versions = {}
107
+ module_queue << full_name
108
+ until module_queue.empty?
109
+ module_full_name = module_queue.shift
110
+ already_added = modules_versions.include? module_full_name
111
+ unless already_added
112
+ author, module_name = module_full_name.split "/"
113
+ module_versions = get_metadata(author, module_name)
114
+ dependencies = module_versions.map {|v| v.dependency_names }.flatten
115
+ module_queue += dependencies
116
+ modules_versions[module_full_name] = module_versions.map { |v| v.to_version }
117
+ end
118
+ end
119
+ raise ModuleNotFound if modules_versions.values == [[]]
120
+ modules_versions
121
+ end
122
+
123
+ def get_module_buffer(author, name, version)
124
+ @repo.get_module(author, name, version) or raise ModuleNotFound
125
+ end
126
+
147
127
  def get_metadata(author, module_name)
148
128
  @repo.get_metadata(author, module_name).map {|metadata| ModuleMetadata.new(metadata)}
149
129
  end
150
130
  end
151
131
  end
132
+
133
+ class ModuleNotFound < Exception
134
+ end
@@ -0,0 +1,31 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2013 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
+ class Array
19
+ # Like 'uniq' with a block, but also works on Ruby < 1.9
20
+ def unique_by
21
+ attr_to_element = {}
22
+ select do |element|
23
+ attribute = yield(element)
24
+ is_duplicate = attr_to_element.include? attribute
25
+ unless is_duplicate
26
+ attr_to_element[yield(element)] = element
27
+ end
28
+ !is_duplicate
29
+ end
30
+ end
31
+ end
@@ -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.0.1"
19
+ VERSION = "0.0.2"
20
20
  end
@@ -16,12 +16,12 @@
16
16
 
17
17
  require 'spec_helper'
18
18
 
19
- module PuppetLibrary
20
- describe ModuleRepo do
19
+ module PuppetLibrary::ModuleRepo
20
+ describe Directory do
21
21
  include ModuleSpecHelper
22
22
 
23
23
  let(:module_dir) { "/tmp/#{$$}" }
24
- let(:module_repo) { ModuleRepo.new(module_dir) }
24
+ let(:module_repo) { Directory.new(module_dir) }
25
25
 
26
26
  before do
27
27
  FileUtils.mkdir_p module_dir
@@ -0,0 +1,97 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2013 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::ModuleRepo
21
+ describe Multi do
22
+ let(:subrepo_one) { double('subrepo_one').as_null_object }
23
+ let(:subrepo_two) { double('subrepo_two').as_null_object }
24
+ let(:multi_repo) do
25
+ repo = Multi.new
26
+ repo.add_repo(subrepo_one)
27
+ repo.add_repo(subrepo_two)
28
+ return repo
29
+ end
30
+
31
+ describe "#get_module" do
32
+ before do
33
+ end
34
+
35
+ context "when the module is found in a subrepository" do
36
+ it "returns the module from the first subrepo it's found in" do
37
+ expect(subrepo_one).to receive(:get_module).with("puppetlabs", "apache", "1.0.0").and_return("puppetlabs/apache module: 1.0.0")
38
+ expect(subrepo_two).not_to receive(:get_module)
39
+
40
+ mod = multi_repo.get_module("puppetlabs", "apache", "1.0.0")
41
+
42
+ expect(mod).to eq "puppetlabs/apache module: 1.0.0"
43
+ end
44
+ end
45
+
46
+ context "when the module is not found in any subrepository" do
47
+ it "returns nil" do
48
+ expect(subrepo_one).to receive(:get_module).with("puppetlabs", "nonexistant", "1.0.0").and_return(nil)
49
+ expect(subrepo_two).to receive(:get_module).with("puppetlabs", "nonexistant", "1.0.0").and_return(nil)
50
+
51
+ mod = multi_repo.get_module("puppetlabs", "nonexistant", "1.0.0")
52
+
53
+ expect(mod).to be_nil
54
+ end
55
+ end
56
+ end
57
+
58
+ describe "#get_metadata" do
59
+ context "when versions of the module are found in subrepositories" do
60
+ it "returns the metadata in an array" do
61
+ apache_module_metadata_one = { "name" => "apache", "version" => "1.0.0" }
62
+ apache_module_metadata_two = { "name" => "apache", "version" => "2.0.0" }
63
+ expect(subrepo_one).to receive(:get_metadata).with("puppetlabs", "apache").and_return([apache_module_metadata_one])
64
+ expect(subrepo_two).to receive(:get_metadata).with("puppetlabs", "apache").and_return([apache_module_metadata_two])
65
+
66
+ metadata_list = multi_repo.get_metadata("puppetlabs", "apache")
67
+
68
+ expect(metadata_list).to eq [ apache_module_metadata_one, apache_module_metadata_two ]
69
+ end
70
+ end
71
+
72
+ context "when no versions of the module are found in any subrepository" do
73
+ it "returns an empty array" do
74
+ expect(subrepo_one).to receive(:get_metadata).with("puppetlabs", "apache").and_return([])
75
+ expect(subrepo_two).to receive(:get_metadata).with("puppetlabs", "apache").and_return([])
76
+
77
+ metadata_list = multi_repo.get_metadata("puppetlabs", "apache")
78
+
79
+ expect(metadata_list).to be_empty
80
+ end
81
+ end
82
+
83
+ context "when the same version of a module is found in multiple repositories" do
84
+ it "returns the one from the first repository it appears in" do
85
+ apache_module_metadata_one = { "name" => "apache", "version" => "1.0.0", "repo" => "one" }
86
+ apache_module_metadata_two = { "name" => "apache", "version" => "1.0.0", "repo" => "two" }
87
+ expect(subrepo_one).to receive(:get_metadata).with("puppetlabs", "apache").and_return([apache_module_metadata_one])
88
+ expect(subrepo_two).to receive(:get_metadata).with("puppetlabs", "apache").and_return([apache_module_metadata_two])
89
+
90
+ metadata_list = multi_repo.get_metadata("puppetlabs", "apache")
91
+
92
+ expect(metadata_list).to eq [ apache_module_metadata_one ]
93
+ end
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,95 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2013 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
21
+ describe PuppetLibrary do
22
+ let(:module_repo) do
23
+ module_repo = double(ModuleRepo::Multi)
24
+ allow(ModuleRepo::Multi).to receive(:new).and_return(module_repo)
25
+ return module_repo
26
+ end
27
+ let(:server) do
28
+ server = double(Server)
29
+ allow(Server).to receive(:new).and_return(server)
30
+ return server
31
+ end
32
+ let(:log) { double('log').as_null_object }
33
+ let(:library) { PuppetLibrary.new(log) }
34
+ let(:default_options) {{ :app => server, :Host => "0.0.0.0", :Port => "9292"}}
35
+ before do
36
+ allow(Rack::Server).to receive(:start)
37
+ end
38
+
39
+ def default_options_with(substitutions)
40
+ default_options.clone.tap do |options|
41
+ substitutions.each do |k, v|
42
+ options[k] = v
43
+ end
44
+ end
45
+ end
46
+
47
+ describe "#go" do
48
+ context "when specifying a bad option" do
49
+ it "prints the usage" do
50
+ expect(log).to receive(:puts).with(/invalid option: --die\nUsage:/)
51
+
52
+ library.go(["--die"])
53
+ end
54
+ end
55
+
56
+ context "when specifying no options" do
57
+ it "runs the server with the default options" do
58
+ expect(Rack::Server).to receive(:start).with(default_options)
59
+
60
+ library.go([])
61
+ end
62
+ end
63
+
64
+ context "when specifying --port option" do
65
+ it "runs the server with the specified port" do
66
+ expect(Rack::Server).to receive(:start).with(default_options_with(:Port => "8080"))
67
+
68
+ library.go(["--port", "8080"])
69
+ end
70
+ end
71
+
72
+ context "when specifying --bind-host option" do
73
+ it "runs the server with the specified bind host" do
74
+ expect(Rack::Server).to receive(:start).with(default_options_with(:Host => "localhost"))
75
+
76
+ library.go(["--bind-host", "localhost"])
77
+ end
78
+ end
79
+
80
+ it "adds a module repository to the server for each module directory" do
81
+ expect(Server).to receive(:new).with(module_repo).and_return(server)
82
+ expect(module_repo).to receive(:add_repo).twice
83
+ expect(Rack::Server).to receive(:start).with(default_options)
84
+
85
+ library.go(["--module-dir", "dir1", "--module-dir", "dir2"])
86
+ end
87
+
88
+ it "logs the server options" do
89
+ expect(log).to receive(:puts).with(/Port: 9292/)
90
+ expect(log).to receive(:puts).with(/Host: 0\.0\.0\.0/)
91
+ library.go([])
92
+ end
93
+ end
94
+ end
95
+ end
data/spec/util_spec.rb ADDED
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # Puppet Library
3
+ # Copyright (C) 2013 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
+ describe 'util' do
21
+ describe Array do
22
+ describe "#unique_by" do
23
+ it "behaves like #uniq with a block, but works with Ruby < 1.9" do
24
+ son = { "name" => "john", "age" => 10 }
25
+ dad = { "name" => "john", "age" => 40 }
26
+ mom = { "name" => "jane", "age" => 40 }
27
+
28
+ family = [son, dad, mom]
29
+ expect(family.unique_by {|p| p["name"]}).to eq [son, mom]
30
+ end
31
+ end
32
+ end
33
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: puppet-library
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - drrb
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-30 00:00:00.000000000 Z
11
+ date: 2014-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -166,17 +166,25 @@ files:
166
166
  - LICENSE.txt
167
167
  - README.md
168
168
  - Rakefile
169
+ - TODO.yml
169
170
  - bin/puppet-library
170
171
  - config.ru
171
172
  - lib/puppet_library.rb
172
- - lib/puppet_library/module_repo.rb
173
+ - lib/puppet_library/module_metadata.rb
174
+ - lib/puppet_library/module_repo/directory.rb
175
+ - lib/puppet_library/module_repo/multi.rb
176
+ - lib/puppet_library/puppet_library.rb
173
177
  - lib/puppet_library/server.rb
178
+ - lib/puppet_library/util.rb
174
179
  - lib/puppet_library/version.rb
175
180
  - puppet-library.gemspec
176
- - spec/module_repo_spec.rb
181
+ - spec/module_repo/directory_spec.rb
182
+ - spec/module_repo/multi_spec.rb
177
183
  - spec/module_spec_helper.rb
184
+ - spec/puppet_library_spec.rb
178
185
  - spec/server_spec.rb
179
186
  - spec/spec_helper.rb
187
+ - spec/util_spec.rb
180
188
  homepage: https://github.com/drrb/puppet-library
181
189
  licenses:
182
190
  - GPL-3
@@ -202,7 +210,10 @@ signing_key:
202
210
  specification_version: 4
203
211
  summary: Puppet Library is a private Puppet module server that's compatible with librarian-puppet.
204
212
  test_files:
205
- - spec/module_repo_spec.rb
213
+ - spec/module_repo/directory_spec.rb
214
+ - spec/module_repo/multi_spec.rb
206
215
  - spec/module_spec_helper.rb
216
+ - spec/puppet_library_spec.rb
207
217
  - spec/server_spec.rb
208
218
  - spec/spec_helper.rb
219
+ - spec/util_spec.rb