puppet-library 0.0.1 → 0.0.2

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
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