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 +4 -4
- data/.licenseignore +1 -0
- data/Rakefile +12 -0
- data/TODO.yml +5 -0
- data/bin/puppet-library +1 -33
- data/config.ru +2 -0
- data/lib/puppet_library.rb +8 -2
- data/lib/puppet_library/module_metadata.rb +67 -0
- data/lib/puppet_library/{module_repo.rb → module_repo/directory.rb} +4 -2
- data/lib/puppet_library/module_repo/multi.rb +43 -0
- data/lib/puppet_library/puppet_library.rb +102 -0
- data/lib/puppet_library/server.rb +66 -83
- data/lib/puppet_library/util.rb +31 -0
- data/lib/puppet_library/version.rb +1 -1
- data/spec/{module_repo_spec.rb → module_repo/directory_spec.rb} +3 -3
- data/spec/module_repo/multi_spec.rb +97 -0
- data/spec/puppet_library_spec.rb +95 -0
- data/spec/util_spec.rb +33 -0
- metadata +16 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 038f863a597766d136e7db4d8f71245844334d7c
|
4
|
+
data.tar.gz: 0f98e71f5110f3875d4c03a401446bf400faa0bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 210fbe7f939854063796aacf44bcdd00da819f3ce97ede62ed58d00ad8c7cd787630aba645bbd460064a5f142da86613b65c920f7995bade1ded406fa049d6b6
|
7
|
+
data.tar.gz: 4978484237188df4973d38aa8880dbfe3829d17753714f8f20cbb29bf85fbbb6426facb137fb71aefe4125e34dcf690142adf45747c5bffc869009abdb825458
|
data/.licenseignore
CHANGED
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
data/bin/puppet-library
CHANGED
@@ -22,37 +22,5 @@ require "puppet_library"
|
|
22
22
|
require 'optparse'
|
23
23
|
|
24
24
|
module PuppetLibrary
|
25
|
-
|
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
|
data/lib/puppet_library.rb
CHANGED
@@ -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
|
19
|
-
|
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
|
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/
|
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
|
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
|
-
|
100
|
-
|
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
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
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 #{
|
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
|
-
|
81
|
+
|
138
82
|
content_type "application/octet-stream"
|
139
|
-
|
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,12 +16,12 @@
|
|
16
16
|
|
17
17
|
require 'spec_helper'
|
18
18
|
|
19
|
-
module PuppetLibrary
|
20
|
-
describe
|
19
|
+
module PuppetLibrary::ModuleRepo
|
20
|
+
describe Directory do
|
21
21
|
include ModuleSpecHelper
|
22
22
|
|
23
23
|
let(:module_dir) { "/tmp/#{$$}" }
|
24
|
-
let(:module_repo) {
|
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.
|
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:
|
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/
|
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/
|
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/
|
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
|