puppet-library 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +19 -0
- data/.licenseignore +1 -0
- data/.simplecov +21 -0
- data/.travis.yml +25 -0
- data/Gemfile +21 -0
- data/LICENSE.txt +676 -0
- data/README.md +89 -0
- data/Rakefile +50 -0
- data/bin/puppet-library +58 -0
- data/config.ru +20 -0
- data/lib/puppet_library.rb +19 -0
- data/lib/puppet_library/module_repo.rb +44 -0
- data/lib/puppet_library/server.rb +151 -0
- data/lib/puppet_library/version.rb +20 -0
- data/puppet-library.gemspec +50 -0
- data/spec/module_repo_spec.rb +80 -0
- data/spec/module_spec_helper.rb +51 -0
- data/spec/server_spec.rb +170 -0
- data/spec/spec_helper.rb +21 -0
- metadata +208 -0
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# Puppet Library
|
2
|
+
|
3
|
+
A server for your Puppet modules. Compatible with [librarian-puppet](http://librarian-puppet.com).
|
4
|
+
|
5
|
+
[](https://travis-ci.org/drrb/puppet-library)
|
6
|
+
[](https://coveralls.io/r/drrb/puppet-library)
|
7
|
+
|
8
|
+
Puppet library serves packaged (`tar.gz`) modules from a directory of your choosing in the same format as [the Puppet Forge](http://forge.puppetlabs.com).
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Install the server as a Gem:
|
13
|
+
|
14
|
+
$ gem install puppet-library
|
15
|
+
|
16
|
+
## Getting Started
|
17
|
+
|
18
|
+
Create a module directory and add the modules to it
|
19
|
+
|
20
|
+
$ mkdir modules
|
21
|
+
$ wget -P modules/ forge.puppetlabs.com/system/releases/p/puppetlabs/puppetlabs-apache-0.9.0.tar.gz
|
22
|
+
$ wget -P modules/ forge.puppetlabs.com/system/releases/p/puppetlabs/puppetlabs-concat-1.0.0.tar.gz
|
23
|
+
$ wget -P modules/ forge.puppetlabs.com/system/releases/p/puppetlabs/puppetlabs-stdlib-2.4.0.tar.gz
|
24
|
+
|
25
|
+
Start the server
|
26
|
+
|
27
|
+
$ puppet-library
|
28
|
+
|
29
|
+
Point librarian-puppet to the server
|
30
|
+
|
31
|
+
$ cat > Puppetfile <<EOF
|
32
|
+
forge 'http://localhost:9292'
|
33
|
+
|
34
|
+
mod 'puppetlabs/apache', '0.9.0'
|
35
|
+
EOF
|
36
|
+
|
37
|
+
Resolve and download the modules
|
38
|
+
|
39
|
+
$ librarian-puppet install
|
40
|
+
|
41
|
+
## Usage
|
42
|
+
|
43
|
+
Run the server
|
44
|
+
|
45
|
+
$ puppet-library
|
46
|
+
|
47
|
+
Serve modules from a specific directory
|
48
|
+
|
49
|
+
$ puppet-library --module-dir /var/puppet-modules
|
50
|
+
|
51
|
+
Serve modules on a specific port
|
52
|
+
|
53
|
+
$ puppet-library --port 8888
|
54
|
+
|
55
|
+
See all options
|
56
|
+
|
57
|
+
$ puppet-library --help
|
58
|
+
|
59
|
+
## Contributing
|
60
|
+
|
61
|
+
1. Fork it
|
62
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
63
|
+
3. Make your changes, and add tests for them
|
64
|
+
4. Test your changes (`rake`)
|
65
|
+
5. Commit your changes (`git commit -am 'Add some feature'`)
|
66
|
+
6. Push to the branch (`git push origin my-new-feature`)
|
67
|
+
7. Create new Pull Request
|
68
|
+
|
69
|
+
## Acknowledgements
|
70
|
+
|
71
|
+
This project was inspired by [dalen/simple-puppet-forge](https://github.com/dalen/simple-puppet-forge).
|
72
|
+
|
73
|
+
## License
|
74
|
+
|
75
|
+
Puppet Library
|
76
|
+
Copyright (C) 2013 drrb
|
77
|
+
|
78
|
+
This program is free software: you can redistribute it and/or modify
|
79
|
+
it under the terms of the GNU General Public License as published by
|
80
|
+
the Free Software Foundation, either version 3 of the License, or
|
81
|
+
(at your option) any later version.
|
82
|
+
|
83
|
+
This program is distributed in the hope that it will be useful,
|
84
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
85
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
86
|
+
GNU General Public License for more details.
|
87
|
+
|
88
|
+
You should have received a copy of the GNU General Public License
|
89
|
+
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
data/Rakefile
ADDED
@@ -0,0 +1,50 @@
|
|
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 'bundler/gem_tasks'
|
19
|
+
require 'rspec/core/rake_task'
|
20
|
+
require 'coveralls/rake/task'
|
21
|
+
|
22
|
+
RSpec::Core::RakeTask.new(:spec)
|
23
|
+
Coveralls::RakeTask.new
|
24
|
+
|
25
|
+
task :default => [:spec, 'coveralls:push']
|
26
|
+
|
27
|
+
desc "Check it works on all local rubies"
|
28
|
+
task :verify do
|
29
|
+
system "rvm all do rake spec check-license"
|
30
|
+
end
|
31
|
+
|
32
|
+
desc "Check all files for license headers"
|
33
|
+
task "check-license" do
|
34
|
+
puts "Checking that all program files contain license headers"
|
35
|
+
|
36
|
+
files = `git ls-files`.split "\n"
|
37
|
+
ignored_files = File.read(".licenseignore").split("\n") << ".licenseignore"
|
38
|
+
offending_files = files.reject { |file| File.read(file).include? "WITHOUT ANY WARRANTY" } - ignored_files
|
39
|
+
if offending_files.empty?
|
40
|
+
puts "Done"
|
41
|
+
else
|
42
|
+
abort("ERROR: THE FOLLOWING FILES HAVE NO LICENSE HEADERS: \n" + offending_files.join("\n"))
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
desc "Print the version number"
|
47
|
+
task "version" do
|
48
|
+
puts PuppetLibrary::VERSION
|
49
|
+
end
|
50
|
+
|
data/bin/puppet-library
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
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
|
+
lib_path = File.join(File.dirname(__FILE__), '..', 'lib')
|
19
|
+
$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include? lib_path
|
20
|
+
|
21
|
+
require "puppet_library"
|
22
|
+
require 'optparse'
|
23
|
+
|
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
|
+
})
|
58
|
+
end
|
data/config.ru
ADDED
@@ -0,0 +1,20 @@
|
|
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 'puppet_library'
|
19
|
+
|
20
|
+
run PuppetLibrary::Server
|
@@ -0,0 +1,19 @@
|
|
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 "puppet_library/server"
|
19
|
+
require "puppet_library/version"
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# Puppet Library
|
2
|
+
# Copyright (C) 2013 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
|
+
require 'rubygems/package'
|
17
|
+
require 'zlib'
|
18
|
+
|
19
|
+
module PuppetLibrary
|
20
|
+
class ModuleRepo
|
21
|
+
def initialize(module_dir)
|
22
|
+
@module_dir = module_dir
|
23
|
+
end
|
24
|
+
|
25
|
+
def get_module(author, name, version)
|
26
|
+
file_name = "#{author}-#{name}-#{version}.tar.gz"
|
27
|
+
path = File.join(File.expand_path(@module_dir), file_name)
|
28
|
+
if File.exist? path
|
29
|
+
File.open(path, 'r')
|
30
|
+
else
|
31
|
+
nil
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def get_metadata(author, module_name)
|
36
|
+
Dir["#{@module_dir}/#{author}-#{module_name}*"].map do |module_path|
|
37
|
+
tar = Gem::Package::TarReader.new(Zlib::GzipReader.open(module_path))
|
38
|
+
tar.rewind
|
39
|
+
metadata_file = tar.find {|e| e.full_name =~ /[^\/]+\/metadata\.json/}
|
40
|
+
JSON.parse(metadata_file.read)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,151 @@
|
|
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
|
+
require 'sinatra/base'
|
18
|
+
require 'json'
|
19
|
+
|
20
|
+
require 'puppet_library/module_repo'
|
21
|
+
|
22
|
+
class Hash
|
23
|
+
def deep_merge(other)
|
24
|
+
merge(other) do |key, old_val, new_val|
|
25
|
+
if old_val.instance_of? Array
|
26
|
+
old_val + new_val
|
27
|
+
else
|
28
|
+
new_val
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
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
|
+
class Server < Sinatra::Base
|
86
|
+
|
87
|
+
def initialize(module_repo = ModuleRepo.new("modules"))
|
88
|
+
super(nil)
|
89
|
+
@repo = module_repo
|
90
|
+
end
|
91
|
+
|
92
|
+
configure do
|
93
|
+
enable :logging
|
94
|
+
end
|
95
|
+
|
96
|
+
get "/:author/:module.json" do
|
97
|
+
author = params[:author]
|
98
|
+
module_name = params[:module]
|
99
|
+
modules = get_metadata(author, module_name)
|
100
|
+
if modules.empty?
|
101
|
+
status 410
|
102
|
+
{"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
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
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 == [[]]
|
126
|
+
status 410
|
127
|
+
{"error" => "Module #{full_name} not found"}.to_json
|
128
|
+
else
|
129
|
+
modules_versions.to_json
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
get "/modules/:author-:module-:version.tar.gz" do
|
134
|
+
author = params[:author]
|
135
|
+
name = params[:module]
|
136
|
+
version = params[:version]
|
137
|
+
buffer = @repo.get_module(author, name, version)
|
138
|
+
content_type "application/octet-stream"
|
139
|
+
if buffer.nil?
|
140
|
+
status 404
|
141
|
+
else
|
142
|
+
attachment "#{author}-#{name}-#{version}.tar.gz"
|
143
|
+
buffer
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
def get_metadata(author, module_name)
|
148
|
+
@repo.get_metadata(author, module_name).map {|metadata| ModuleMetadata.new(metadata)}
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
@@ -0,0 +1,20 @@
|
|
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
|
+
VERSION = "0.0.1"
|
20
|
+
end
|