puppet-library 0.13.0 → 0.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -7
- data/.gitignore +1 -1
- data/CHANGELOG.yml +6 -0
- data/README.md +21 -5
- data/TODO.yml +1 -3
- data/config.ru +4 -4
- data/lib/puppet_library/app/views/index.haml +2 -1
- data/lib/puppet_library/archive/archive_reader.rb +1 -1
- data/lib/puppet_library/forge/directory.rb +14 -7
- data/lib/puppet_library/forge/forge.rb +4 -0
- data/lib/puppet_library/forge/git_repository.rb +26 -16
- data/lib/puppet_library/forge/source.rb +18 -11
- data/lib/puppet_library/util/git.rb +4 -4
- data/lib/puppet_library/util/logging.rb +12 -3
- data/lib/puppet_library/util/temp_dir.rb +8 -1
- data/lib/puppet_library/version.rb +1 -1
- data/puppet-library.gemspec +2 -2
- data/spec/forge/directory_spec.rb +47 -0
- data/spec/forge/git_repository_spec.rb +40 -10
- data/spec/forge/source_spec.rb +48 -28
- data/spec/server_spec.rb +1 -1
- data/spec/spec_helper.rb +17 -5
- data/spec/util/git_spec.rb +8 -7
- data/spec/util/temp_dir_spec.rb +19 -3
- metadata +320 -127
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
|
-
---
|
2
|
-
SHA1:
|
3
|
-
|
4
|
-
|
5
|
-
SHA512:
|
6
|
-
|
7
|
-
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: ce0573aac08832b970f50871291d13f4487e8495
|
4
|
+
data.tar.gz: d5f1fd926455ca4fbb87c7570797b002b0cf4bca
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 123f603ff5ec60ec88f41bb7120e338e83e349e4d566dd11a1be46be406ae5f170577203d7c21a46eb7ed426da02ef25f71304d843cfb3589d84465a6d038961
|
7
|
+
data.tar.gz: 948cc9e9a048709d05ec1d53a9b2c0d90225d9b0026383fa48afc5f3ee442f1ebc08bcf62deaee591e7c50ca5e6218e0295007da0e57e140cce67c377590ba48
|
data/.gitignore
CHANGED
data/CHANGELOG.yml
CHANGED
@@ -91,3 +91,9 @@
|
|
91
91
|
- tag: v0.13.0
|
92
92
|
changes:
|
93
93
|
- Fixed "Invalid gemspec" error (#5)
|
94
|
+
- tag: v0.14.0
|
95
|
+
changes:
|
96
|
+
- Use `metadata.json` in place of `Modulefile` if it exists (and `Modulefile` doesn't exist)
|
97
|
+
- Ignore corrupt module files on disk
|
98
|
+
- Added logging for when module files can't be read from disk
|
99
|
+
- Recurse into module directories when serving modules from disk
|
data/README.md
CHANGED
@@ -2,12 +2,12 @@
|
|
2
2
|
|
3
3
|
A private Puppet Forge. Compatible with [librarian-puppet](http://librarian-puppet.com).
|
4
4
|
|
5
|
-
[![Build Status](https://travis-ci.org/drrb/puppet-library.
|
6
|
-
[![Coverage Status](https://
|
7
|
-
[![Code Climate](https://
|
5
|
+
[![Build Status](https://api.travis-ci.org/drrb/puppet-library.svg)](https://travis-ci.org/drrb/puppet-library)
|
6
|
+
[![Coverage Status](https://img.shields.io/coveralls/drrb/puppet-library.svg)](https://coveralls.io/r/drrb/puppet-library)
|
7
|
+
[![Code Climate](https://img.shields.io/codeclimate/github/drrb/puppet-library.svg)](https://codeclimate.com/github/drrb/puppet-library)
|
8
8
|
|
9
|
-
[![Gem Version](https://badge.fury.io/rb/puppet-library.
|
10
|
-
[![Dependency Status](https://gemnasium.com/drrb/puppet-library.
|
9
|
+
[![Gem Version](https://badge.fury.io/rb/puppet-library.svg)](http://badge.fury.io/rb/puppet-library)
|
10
|
+
[![Dependency Status](https://gemnasium.com/drrb/puppet-library.svg)](https://gemnasium.com/drrb/puppet-library)
|
11
11
|
|
12
12
|
Puppet Library serves Puppet modules in the same format as [the Puppet Forge](http://forge.puppetlabs.com). This allows you to create a private Puppet Forge and manage all the modules you use completely within your infrastructure.
|
13
13
|
|
@@ -18,6 +18,10 @@ Plugins can be created to serve modules from arbitrary sources. Puppet Library c
|
|
18
18
|
- serving modules from source on disk
|
19
19
|
- serving modules from Git repositories using tags as version numbers!
|
20
20
|
|
21
|
+
## Demo
|
22
|
+
|
23
|
+
Puppet Library has a web UI to browse the modules. A demo is available [here](http://puppet-library.herokuapp.com).
|
24
|
+
|
21
25
|
## Installation
|
22
26
|
|
23
27
|
Install the server as a Gem:
|
@@ -96,18 +100,30 @@ Puppet Library contains built-in support for:
|
|
96
100
|
|
97
101
|
## Compatibility with other tools
|
98
102
|
|
103
|
+
### Dependency Resolution/Installation
|
104
|
+
|
99
105
|
Puppet Library currently supports:
|
100
106
|
- search with Puppet (`puppet module search apache`)
|
101
107
|
- dependency resolution and installation with Puppet (`puppet module install puppetlabs/apache`)
|
102
108
|
- dependency resolution and installation with [librarian-puppet](http://librarian-puppet.com)
|
103
109
|
- installation with [r10k](https://github.com/adrienthebo/r10k)
|
104
110
|
|
111
|
+
### Ruby
|
112
|
+
|
105
113
|
Puppet Library is tested against Ruby versions:
|
106
114
|
- 1.8.7
|
107
115
|
- 1.9.3
|
108
116
|
- 2.0.0
|
109
117
|
- 2.1.0
|
110
118
|
|
119
|
+
### Puppet
|
120
|
+
|
121
|
+
Puppet Library implements version 1 of the Forge API, and supports reading
|
122
|
+
module metadata from modules' Modulefiles. This means that Puppet Library
|
123
|
+
can currently only work with Puppet < 3.6, which uses the new Forge API (v3)
|
124
|
+
and has switched to using `metadata.json` instead of `Modulefile`. Progress
|
125
|
+
can be tracked [here](https://github.com/drrb/puppet-library/issues?milestone=1).
|
126
|
+
|
111
127
|
## Config file (EXPERIMENTAL)
|
112
128
|
|
113
129
|
Instead of specifying command-line options, you can configure Puppet Library with a configuration file.
|
data/TODO.yml
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
features:
|
2
|
+
- Support Forge API v3
|
2
3
|
- Git repo forge:
|
3
4
|
- make it more flexible:
|
4
5
|
- fail gracefully if we can't contact the remote repo
|
@@ -18,9 +19,6 @@ features:
|
|
18
19
|
- Config APIs:
|
19
20
|
- documentation
|
20
21
|
|
21
|
-
bugs:
|
22
|
-
- Using directory forge and Puppet Forge proxy doesn't list Puppet Forge modules on the index page unless you search
|
23
|
-
|
24
22
|
dubious_features:
|
25
23
|
- Proxy modules' source in a directory (supported individually for now: should we just leave it that way?)
|
26
24
|
- Make proxy cache TTL configurable
|
data/config.ru
CHANGED
@@ -19,10 +19,10 @@ require 'rubygems'
|
|
19
19
|
require 'puppet_library'
|
20
20
|
|
21
21
|
server = PuppetLibrary::Server.configure do
|
22
|
-
|
23
|
-
forge :directory do
|
24
|
-
|
25
|
-
end
|
22
|
+
## My custom modules
|
23
|
+
#forge :directory do
|
24
|
+
# path "/var/puppet/modules"
|
25
|
+
#end
|
26
26
|
|
27
27
|
# Unreleased versions from Github
|
28
28
|
forge :git_repository do
|
@@ -22,7 +22,8 @@
|
|
22
22
|
|
23
23
|
:javascript
|
24
24
|
$(document).ready(function() {
|
25
|
-
|
25
|
+
var source = "modules.json#{ query.nil? ? '' : '?q=' + query }";
|
26
|
+
$.getJSON(source, function(modules) {
|
26
27
|
$.each(modules, function(index, module) {
|
27
28
|
var item = $("<li/>");
|
28
29
|
item.append($("<b/>").append($("<a/>").attr("href", module.full_name).text(module.full_name)));
|
@@ -26,7 +26,7 @@ module PuppetLibrary::Archive
|
|
26
26
|
def read_entry(entry_name_regex)
|
27
27
|
tar = Gem::Package::TarReader.new(Zlib::GzipReader.open(@path))
|
28
28
|
tar.rewind
|
29
|
-
entry = tar.find {|e| e.full_name =~ entry_name_regex } or raise "Couldn't find entry in archive"
|
29
|
+
entry = tar.find {|e| e.full_name =~ entry_name_regex } or raise "Couldn't find entry in archive matching #{entry_name_regex.inspect}"
|
30
30
|
entry.read
|
31
31
|
end
|
32
32
|
end
|
@@ -65,16 +65,23 @@ module PuppetLibrary::Forge
|
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
68
|
+
def get_all_metadata
|
69
|
+
get_metadata("*", "*")
|
70
|
+
end
|
71
|
+
|
68
72
|
def get_metadata(author, module_name)
|
69
|
-
Dir["#{@module_dir.path}
|
70
|
-
|
71
|
-
metadata_file = archive.read_entry %r[[^/]+/metadata\.json$]
|
72
|
-
JSON.parse(metadata_file)
|
73
|
-
end
|
73
|
+
archives = Dir["#{@module_dir.path}/**/#{author}-#{module_name}-*.tar.gz"]
|
74
|
+
archives.map {|path| read_metadata(path) }.compact
|
74
75
|
end
|
75
76
|
|
76
|
-
|
77
|
-
|
77
|
+
private
|
78
|
+
def read_metadata(archive_path)
|
79
|
+
archive = PuppetLibrary::Archive::ArchiveReader.new(archive_path)
|
80
|
+
metadata_file = archive.read_entry %r[[^/]+/metadata\.json$]
|
81
|
+
JSON.parse(metadata_file)
|
82
|
+
rescue => error
|
83
|
+
warn "Error reading from module archive #{archive_path}: #{error}"
|
84
|
+
return nil
|
78
85
|
end
|
79
86
|
end
|
80
87
|
end
|
@@ -14,8 +14,12 @@
|
|
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
16
|
|
17
|
+
require 'puppet_library/util/logging'
|
18
|
+
|
17
19
|
module PuppetLibrary::Forge
|
18
20
|
class Forge
|
21
|
+
include PuppetLibrary::Util::Logging
|
22
|
+
|
19
23
|
def prime
|
20
24
|
end
|
21
25
|
|
@@ -60,8 +60,8 @@ module PuppetLibrary::Forge
|
|
60
60
|
super(self)
|
61
61
|
@version_tag_regex = version_tag_regex
|
62
62
|
@git = git
|
63
|
-
@
|
64
|
-
@tags_cache = PuppetLibrary::Http::Cache::InMemory.new
|
63
|
+
@metadata_cache = PuppetLibrary::Http::Cache::InMemory.new(60)
|
64
|
+
@tags_cache = PuppetLibrary::Http::Cache::InMemory.new(60)
|
65
65
|
end
|
66
66
|
|
67
67
|
def prime
|
@@ -75,11 +75,11 @@ module PuppetLibrary::Forge
|
|
75
75
|
def get_module(author, name, version)
|
76
76
|
return nil unless tags.include? tag_for(version)
|
77
77
|
|
78
|
-
metadata =
|
78
|
+
metadata = metadata_for(version)
|
79
79
|
return nil unless metadata["name"] == "#{author}-#{name}"
|
80
80
|
|
81
|
-
|
82
|
-
PuppetLibrary::Archive::Archiver.archive_dir(
|
81
|
+
with_tag_for(version) do |tag_path|
|
82
|
+
PuppetLibrary::Archive::Archiver.archive_dir(tag_path, "#{metadata["name"]}-#{version}") do |archive|
|
83
83
|
archive.add_file("metadata.json", 0644) do |entry|
|
84
84
|
entry.write metadata.to_json
|
85
85
|
end
|
@@ -89,7 +89,7 @@ module PuppetLibrary::Forge
|
|
89
89
|
|
90
90
|
def get_all_metadata
|
91
91
|
tags.map do |tag|
|
92
|
-
|
92
|
+
metadata_for_tag(tag)
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
@@ -106,23 +106,33 @@ module PuppetLibrary::Forge
|
|
106
106
|
@tags_cache.get do
|
107
107
|
tags = @git.tags
|
108
108
|
tags = tags.select {|tag| tag =~ @version_tag_regex }
|
109
|
-
tags = tags.select
|
109
|
+
tags = tags.select do |tag|
|
110
|
+
@git.file_exists?("metadata.json", tag) || @git.file_exists?("Modulefile", tag)
|
111
|
+
end
|
110
112
|
end
|
111
113
|
end
|
112
114
|
|
113
|
-
def
|
114
|
-
@
|
115
|
-
|
116
|
-
|
115
|
+
def metadata_for_tag(tag)
|
116
|
+
@metadata_cache.get(tag) do
|
117
|
+
metadata_file_exists = @git.file_exists?("metadata.json", tag)
|
118
|
+
modulefile_exists = @git.file_exists?("Modulefile", tag)
|
119
|
+
if metadata_file_exists && !modulefile_exists
|
120
|
+
metadata_file = @git.read_file("metadata.json", tag)
|
121
|
+
JSON.parse(metadata_file)
|
122
|
+
else
|
123
|
+
modulefile_source = @git.read_file("Modulefile", tag)
|
124
|
+
modulefile = PuppetLibrary::PuppetModule::Modulefile.parse(modulefile_source)
|
125
|
+
modulefile.to_metadata
|
126
|
+
end
|
117
127
|
end
|
118
128
|
end
|
119
129
|
|
120
|
-
def
|
121
|
-
|
130
|
+
def metadata_for(version)
|
131
|
+
metadata_for_tag(tag_for(version))
|
122
132
|
end
|
123
133
|
|
124
|
-
def
|
125
|
-
@git.
|
134
|
+
def with_tag_for(version, &block)
|
135
|
+
@git.with_tag(tag_for(version), &block)
|
126
136
|
end
|
127
137
|
|
128
138
|
def tag_for(version)
|
@@ -131,7 +141,7 @@ module PuppetLibrary::Forge
|
|
131
141
|
|
132
142
|
def tag_versions
|
133
143
|
tags_to_versions = tags.map do |tag|
|
134
|
-
[
|
144
|
+
[ metadata_for_tag(tag)["version"], tag ]
|
135
145
|
end
|
136
146
|
Hash[tags_to_versions]
|
137
147
|
end
|
@@ -25,7 +25,8 @@ module PuppetLibrary::Forge
|
|
25
25
|
# Metadata (+metadata.json+) is generated on the fly.
|
26
26
|
#
|
27
27
|
# <b>Note:</b>
|
28
|
-
# The module directory must have a +Modulefile+.
|
28
|
+
# The module directory must have either a +metadata.json+ or a +Modulefile+.
|
29
|
+
# If it contains both, +metadata.json+ will be used.
|
29
30
|
#
|
30
31
|
# <b>Usage:</b>
|
31
32
|
#
|
@@ -52,41 +53,47 @@ module PuppetLibrary::Forge
|
|
52
53
|
raise "Module directory '#{module_dir.path}' doesn't exist" unless File.directory? module_dir.path
|
53
54
|
raise "Module directory '#{module_dir.path}' isn't readable" unless File.executable? module_dir.path
|
54
55
|
@module_dir = module_dir
|
55
|
-
@
|
56
|
+
@metadata_cache = PuppetLibrary::Http::Cache::InMemory.new(CACHE_TTL_MILLIS)
|
56
57
|
end
|
57
58
|
|
58
59
|
def get_module(author, name, version)
|
59
60
|
return nil unless this_module?(author, name, version)
|
60
61
|
PuppetLibrary::Archive::Archiver.archive_dir(@module_dir.path, "#{author}-#{name}-#{version}") do |archive|
|
61
62
|
archive.add_file("metadata.json", 0644) do |entry|
|
62
|
-
entry.write
|
63
|
+
entry.write metadata.to_json
|
63
64
|
end
|
64
65
|
end
|
65
66
|
end
|
66
67
|
|
67
68
|
def get_metadata(author, module_name)
|
68
69
|
return [] unless this_module?(author, module_name)
|
69
|
-
[
|
70
|
+
[ metadata ]
|
70
71
|
end
|
71
72
|
|
72
73
|
def get_all_metadata
|
73
|
-
get_metadata(
|
74
|
+
get_metadata(metadata["author"], metadata["name"].split("-").last)
|
74
75
|
end
|
75
76
|
|
76
77
|
private
|
77
78
|
def this_module?(author, module_name, version = nil)
|
78
|
-
same_module =
|
79
|
+
same_module = metadata["name"] == "#{author}-#{module_name}"
|
79
80
|
if version.nil?
|
80
81
|
return same_module
|
81
82
|
else
|
82
|
-
return same_module &&
|
83
|
+
return same_module && metadata["version"] == version
|
83
84
|
end
|
84
85
|
end
|
85
86
|
|
86
|
-
def
|
87
|
-
|
88
|
-
|
89
|
-
|
87
|
+
def metadata
|
88
|
+
@metadata_cache.get "metadata" do
|
89
|
+
metadata_file_path = File.join(@module_dir.path, "metadata.json")
|
90
|
+
modulefile_path = File.join(@module_dir.path, "Modulefile")
|
91
|
+
if File.exist?(metadata_file_path) && ! File.exist?(modulefile_path)
|
92
|
+
JSON.parse(File.read(metadata_file_path))
|
93
|
+
else
|
94
|
+
modulefile = PuppetLibrary::PuppetModule::Modulefile.read(modulefile_path)
|
95
|
+
modulefile.to_metadata
|
96
|
+
end
|
90
97
|
end
|
91
98
|
end
|
92
99
|
end
|
@@ -39,11 +39,11 @@ module PuppetLibrary::Util
|
|
39
39
|
git("tag").split
|
40
40
|
end
|
41
41
|
|
42
|
-
def
|
42
|
+
def with_tag(tag)
|
43
43
|
update_cache!
|
44
44
|
PuppetLibrary::Util::TempDir.use "git" do |path|
|
45
45
|
git "checkout #{tag}", path
|
46
|
-
yield
|
46
|
+
yield(path)
|
47
47
|
end
|
48
48
|
end
|
49
49
|
|
@@ -75,14 +75,14 @@ module PuppetLibrary::Util
|
|
75
75
|
def create_cache
|
76
76
|
@mutex.synchronize do
|
77
77
|
info "Cloning Git repository from #{@source} to #{@git_dir}"
|
78
|
-
git "clone --
|
78
|
+
git "clone --mirror #{@source} #{@git_dir}"
|
79
79
|
FileUtils.touch fetch_file
|
80
80
|
end
|
81
81
|
end
|
82
82
|
|
83
83
|
def update_cache
|
84
84
|
@mutex.synchronize do
|
85
|
-
git "fetch --tags"
|
85
|
+
git "fetch origin --tags --update-head-ok"
|
86
86
|
end
|
87
87
|
end
|
88
88
|
|
@@ -18,12 +18,21 @@ require 'logger'
|
|
18
18
|
|
19
19
|
module PuppetLibrary::Util
|
20
20
|
module Logging
|
21
|
-
|
22
|
-
|
21
|
+
class LogCollector < Array
|
22
|
+
def write(message)
|
23
|
+
self << message
|
24
|
+
end
|
25
|
+
|
26
|
+
def close
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def logs
|
31
|
+
@logs ||= LogCollector.new
|
23
32
|
end
|
24
33
|
|
25
34
|
def logger
|
26
|
-
destination = ENV["TESTING"] ?
|
35
|
+
destination = ENV["TESTING"] ? logs : STDERR
|
27
36
|
@logger ||= Logger.new(destination).tap do |logger|
|
28
37
|
logger.progname = self.class.name
|
29
38
|
logger.level = Logger::DEBUG
|
@@ -21,7 +21,14 @@ module PuppetLibrary::Util
|
|
21
21
|
class TempDir
|
22
22
|
attr_reader :path
|
23
23
|
|
24
|
-
def self.use(name
|
24
|
+
def self.use(name)
|
25
|
+
path = create(name)
|
26
|
+
yield(path)
|
27
|
+
ensure
|
28
|
+
FileUtils.rm_rf path
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.cd(name, &block)
|
25
32
|
path = create(name)
|
26
33
|
Dir.chdir(path, &block)
|
27
34
|
ensure
|
data/puppet-library.gemspec
CHANGED
@@ -47,11 +47,11 @@ Gem::Specification.new do |spec|
|
|
47
47
|
spec.add_development_dependency "gitsu"
|
48
48
|
spec.add_development_dependency "librarian-puppet", "0.9.10" # 0.9.12 breaks on Ruby 1.8.7
|
49
49
|
spec.add_development_dependency "mime-types", "< 2"
|
50
|
-
spec.add_development_dependency "pry"
|
50
|
+
spec.add_development_dependency "pry", "0.9.12.6"
|
51
51
|
spec.add_development_dependency "puppet", "~> 3.3.0"
|
52
52
|
spec.add_development_dependency "rack-test"
|
53
53
|
spec.add_development_dependency "rake"
|
54
|
-
spec.add_development_dependency "rspec"
|
54
|
+
spec.add_development_dependency "rspec", "~> 3.0.0"
|
55
55
|
spec.add_development_dependency "simplecov"
|
56
56
|
|
57
57
|
# Guard has dependencies that don't work with Ruby < 1.9
|