puppet-library 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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
+
@@ -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