puppet-library 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Build Status](https://travis-ci.org/drrb/puppet-library.png?branch=master)](https://travis-ci.org/drrb/puppet-library)
|
6
|
+
[![Coverage Status](https://coveralls.io/repos/drrb/puppet-library/badge.png)](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
|