puppet-library 0.10.0 → 0.11.0
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 +4 -4
- data/CHANGELOG.yml +11 -0
- data/README.md +16 -7
- data/Rakefile +21 -21
- data/TODO.yml +10 -6
- data/bin/puppet-library +0 -1
- data/config.ru +14 -16
- data/features/step_definitions/sinatra_steps.rb +3 -12
- data/lib/puppet_library/forge.rb +1 -0
- data/lib/puppet_library/forge/abstract.rb +2 -1
- data/lib/puppet_library/forge/cache.rb +11 -7
- data/lib/puppet_library/forge/directory.rb +15 -13
- data/lib/puppet_library/forge/forge.rb +25 -0
- data/lib/puppet_library/forge/git_repository.rb +42 -17
- data/lib/puppet_library/forge/multi.rb +11 -1
- data/lib/puppet_library/forge/proxy.rb +14 -9
- data/lib/puppet_library/forge/source.rb +12 -13
- data/lib/puppet_library/http/cache/disk.rb +26 -8
- data/lib/puppet_library/http/cache/in_memory.rb +13 -10
- data/lib/puppet_library/http/cache/noop.rb +4 -1
- data/lib/puppet_library/puppet_library.rb +10 -7
- data/lib/puppet_library/puppet_module/modulefile.rb +5 -1
- data/lib/puppet_library/server.rb +13 -9
- data/lib/puppet_library/util.rb +1 -0
- data/lib/puppet_library/util/config_api.rb +115 -0
- data/lib/puppet_library/util/git.rb +36 -8
- data/lib/puppet_library/util/logging.rb +49 -0
- data/lib/puppet_library/util/patches.rb +21 -0
- data/lib/puppet_library/util/temp_dir.rb +20 -5
- data/lib/puppet_library/version.rb +1 -1
- data/puppet-library.gemspec +2 -0
- data/spec/archive/archive_reader_spec.rb +2 -6
- data/spec/archive/archiver_spec.rb +5 -9
- data/spec/forge/cache_spec.rb +13 -7
- data/spec/forge/directory_spec.rb +31 -18
- data/spec/forge/git_repository_spec.rb +60 -13
- data/spec/forge/multi_spec.rb +16 -0
- data/spec/forge/proxy_spec.rb +18 -0
- data/spec/forge/source_spec.rb +14 -9
- data/spec/http/cache/disk_spec.rb +11 -6
- data/spec/http/cache/in_memory_spec.rb +12 -0
- data/spec/http/cache/noop_spec.rb +6 -0
- data/spec/integration_test_helper.rb +3 -3
- data/spec/module_spec_helper.rb +2 -2
- data/spec/puppet_library_spec.rb +34 -16
- data/spec/puppet_module/modulefile_spec.rb +48 -9
- data/spec/server_spec.rb +28 -1
- data/spec/spec_helper.rb +2 -14
- data/spec/util/config_api_spec.rb +77 -0
- data/spec/util/git_spec.rb +20 -20
- data/spec/util/patches_spec.rb +18 -0
- data/test/directory_forge_integration_test.rb +6 -8
- data/test/offline_git_repo_forge_integration_test.rb +9 -14
- data/test/offline_proxy_forge_integration_test.rb +11 -14
- data/test/online_git_repo_forge_integration_test.rb +7 -8
- data/test/online_proxy_forge_integration_test.rb +10 -13
- data/test/source_forge_integration_test.rb +7 -8
- metadata +35 -2
@@ -17,16 +17,20 @@
|
|
17
17
|
require 'fileutils'
|
18
18
|
require 'monitor'
|
19
19
|
require 'time'
|
20
|
+
require 'open4'
|
21
|
+
require 'puppet_library/util/logging'
|
20
22
|
require 'puppet_library/util/temp_dir'
|
21
23
|
|
22
24
|
module PuppetLibrary::Util
|
23
25
|
class Git
|
26
|
+
include Logging
|
27
|
+
|
24
28
|
DEFAULT_CACHE_TTL_SECONDS = 60
|
25
|
-
def initialize(source,
|
29
|
+
def initialize(source, cache_dir, cache_ttl_seconds = DEFAULT_CACHE_TTL_SECONDS)
|
26
30
|
@source = source
|
27
|
-
@
|
31
|
+
@cache_dir = cache_dir
|
28
32
|
@cache_ttl_seconds = cache_ttl_seconds
|
29
|
-
@git_dir = File.join(@
|
33
|
+
@git_dir = File.join(@cache_dir.path, ".git")
|
30
34
|
@mutex = Monitor.new
|
31
35
|
end
|
32
36
|
|
@@ -48,9 +52,17 @@ module PuppetLibrary::Util
|
|
48
52
|
git "show refs/tags/#{tag}:#{path}"
|
49
53
|
end
|
50
54
|
|
55
|
+
def file_exists?(path, tag)
|
56
|
+
read_file(path, tag)
|
57
|
+
true
|
58
|
+
rescue GitCommandError
|
59
|
+
false
|
60
|
+
end
|
61
|
+
|
51
62
|
def clear_cache!
|
52
63
|
@mutex.synchronize do
|
53
|
-
|
64
|
+
info "Clearing cache for Git repository #{@source} from #{@git_dir}"
|
65
|
+
FileUtils.rm_rf @cache_dir.path
|
54
66
|
end
|
55
67
|
end
|
56
68
|
|
@@ -62,7 +74,8 @@ module PuppetLibrary::Util
|
|
62
74
|
private
|
63
75
|
def create_cache
|
64
76
|
@mutex.synchronize do
|
65
|
-
|
77
|
+
info "Cloning Git repository from #{@source} to #{@git_dir}"
|
78
|
+
git "clone --bare #{@source} #{@git_dir}"
|
66
79
|
FileUtils.touch fetch_file
|
67
80
|
end
|
68
81
|
end
|
@@ -94,10 +107,25 @@ module PuppetLibrary::Util
|
|
94
107
|
end
|
95
108
|
|
96
109
|
def git(command, work_tree = nil)
|
97
|
-
work_tree = @
|
98
|
-
|
99
|
-
|
110
|
+
work_tree = @cache_dir.path unless work_tree
|
111
|
+
run "git --git-dir=#{@git_dir} --work-tree=#{work_tree} #{command}"
|
112
|
+
end
|
113
|
+
|
114
|
+
def run(command)
|
115
|
+
debug command
|
116
|
+
pid, stdin, stdout, stderr = Open4.popen4(command)
|
117
|
+
ignored, status = Process::waitpid2 pid
|
118
|
+
unless status.success?
|
119
|
+
raise GitCommandError, "Error running Git command: #{command}\n#{stdout.read}\n#{stderr.read}"
|
100
120
|
end
|
121
|
+
stdout.read
|
122
|
+
ensure
|
123
|
+
stdin.close
|
124
|
+
stdout.close
|
125
|
+
stderr.close
|
126
|
+
end
|
127
|
+
|
128
|
+
class GitCommandError < StandardError
|
101
129
|
end
|
102
130
|
end
|
103
131
|
end
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Puppet Library
|
2
|
+
# Copyright (C) 2014 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
|
+
|
17
|
+
require 'logger'
|
18
|
+
|
19
|
+
module PuppetLibrary::Util
|
20
|
+
module Logging
|
21
|
+
def log_io
|
22
|
+
@log_io ||= StringIO.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def logger
|
26
|
+
destination = ENV["TESTING"] ? log_io : STDERR
|
27
|
+
@logger ||= Logger.new(destination).tap do |logger|
|
28
|
+
logger.progname = self.class.name
|
29
|
+
logger.level = Logger::DEBUG
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def debug(message)
|
34
|
+
logger.debug message
|
35
|
+
end
|
36
|
+
|
37
|
+
def info(message)
|
38
|
+
logger.info message
|
39
|
+
end
|
40
|
+
|
41
|
+
def warn(message)
|
42
|
+
logger.warn message
|
43
|
+
end
|
44
|
+
|
45
|
+
#def error(message)
|
46
|
+
# logger.error message
|
47
|
+
#end
|
48
|
+
end
|
49
|
+
end
|
@@ -78,6 +78,15 @@ class Array
|
|
78
78
|
merged.deep_merge(map)
|
79
79
|
end
|
80
80
|
end
|
81
|
+
|
82
|
+
def each_in_parallel
|
83
|
+
threads = map do |element|
|
84
|
+
Thread.new do
|
85
|
+
yield(element)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
threads.each &:join
|
89
|
+
end
|
81
90
|
end
|
82
91
|
|
83
92
|
class Hash
|
@@ -92,6 +101,12 @@ class Hash
|
|
92
101
|
end
|
93
102
|
end
|
94
103
|
|
104
|
+
class String
|
105
|
+
def snake_case_to_camel_case
|
106
|
+
split("_").map(&:capitalize).join
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
95
110
|
class Gem::Package::TarReader
|
96
111
|
# Old versions of RubyGems don't include Enumerable in here
|
97
112
|
def find
|
@@ -102,3 +117,9 @@ class Gem::Package::TarReader
|
|
102
117
|
end
|
103
118
|
end
|
104
119
|
end
|
120
|
+
|
121
|
+
class Dir
|
122
|
+
def to_str
|
123
|
+
path
|
124
|
+
end
|
125
|
+
end
|
@@ -29,14 +29,29 @@ module PuppetLibrary::Util
|
|
29
29
|
end
|
30
30
|
|
31
31
|
def self.create(name)
|
32
|
-
|
32
|
+
file = Tempfile.new(name)
|
33
|
+
path = file.path
|
34
|
+
file.unlink
|
35
|
+
FileUtils.mkdir path
|
36
|
+
path
|
33
37
|
end
|
34
38
|
|
35
39
|
def initialize(name)
|
36
|
-
|
37
|
-
@
|
38
|
-
|
39
|
-
|
40
|
+
@path = TempDir.create(name)
|
41
|
+
@remover = Remover.new(@path)
|
42
|
+
ObjectSpace.define_finalizer(self, @remover)
|
43
|
+
end
|
44
|
+
|
45
|
+
class Remover
|
46
|
+
def initialize(path)
|
47
|
+
@path = path
|
48
|
+
end
|
49
|
+
|
50
|
+
def call(*args)
|
51
|
+
if File.directory? @path
|
52
|
+
FileUtils.rm_rf @path
|
53
|
+
end
|
54
|
+
end
|
40
55
|
end
|
41
56
|
end
|
42
57
|
end
|
data/puppet-library.gemspec
CHANGED
@@ -39,6 +39,8 @@ Gem::Specification.new do |spec|
|
|
39
39
|
spec.add_dependency "sinatra"
|
40
40
|
spec.add_dependency "json"
|
41
41
|
spec.add_dependency "haml"
|
42
|
+
spec.add_dependency "docile", ">= 1.0.0"
|
43
|
+
spec.add_dependency "open4"
|
42
44
|
|
43
45
|
spec.add_development_dependency "bundler", "~> 1.3"
|
44
46
|
spec.add_development_dependency "coveralls"
|
@@ -23,11 +23,11 @@ module PuppetLibrary::Archive
|
|
23
23
|
end
|
24
24
|
|
25
25
|
let :source_dir do
|
26
|
-
Tempdir.
|
26
|
+
Tempdir.new("zipping")
|
27
27
|
end
|
28
28
|
|
29
29
|
let :archive do
|
30
|
-
archive = File.join(source_dir, "archive.tgz")
|
30
|
+
archive = File.join(source_dir.path, "archive.tgz")
|
31
31
|
write_tar_gzip!(archive) do |zip|
|
32
32
|
zip.add_file("arrive.txt", 0644) { |entry| entry.write "say hello" }
|
33
33
|
zip.add_file("later/depart.txt", 0644) { |entry| entry.write "say bye" }
|
@@ -35,10 +35,6 @@ module PuppetLibrary::Archive
|
|
35
35
|
archive
|
36
36
|
end
|
37
37
|
|
38
|
-
after do
|
39
|
-
rm_rf source_dir
|
40
|
-
end
|
41
|
-
|
42
38
|
def write_tar_gzip!(file_name)
|
43
39
|
tar = StringIO.new
|
44
40
|
|
@@ -19,10 +19,10 @@ require 'spec_helper'
|
|
19
19
|
module PuppetLibrary::Archive
|
20
20
|
describe Archiver do
|
21
21
|
describe "#archive_dir" do
|
22
|
-
let(:dir) { Tempdir.
|
22
|
+
let(:dir) { Tempdir.new("tozip") }
|
23
23
|
|
24
24
|
def write_file!(filename, content)
|
25
|
-
path = File.join(dir, filename)
|
25
|
+
path = File.join(dir.path, filename)
|
26
26
|
FileUtils.mkdir_p(File.dirname(path))
|
27
27
|
File.open(path, "w") do |file|
|
28
28
|
file.write content
|
@@ -34,19 +34,15 @@ module PuppetLibrary::Archive
|
|
34
34
|
write_file! "later/depart.txt", "say bye"
|
35
35
|
end
|
36
36
|
|
37
|
-
after do
|
38
|
-
rm_rf dir
|
39
|
-
end
|
40
|
-
|
41
37
|
it "tars and gzips a directory and its contents" do
|
42
|
-
buffer = Archiver.archive_dir(dir, "todo")
|
38
|
+
buffer = Archiver.archive_dir(dir.path, "todo")
|
43
39
|
|
44
40
|
expect(buffer).to be_tgz_with "todo/arrive.txt", "say hello"
|
45
41
|
expect(buffer).to be_tgz_with "todo/later/depart.txt", "say bye"
|
46
42
|
end
|
47
43
|
|
48
44
|
it "allows you to inject files from a block" do
|
49
|
-
buffer = Archiver.archive_dir(dir, "todo") do |archive|
|
45
|
+
buffer = Archiver.archive_dir(dir.path, "todo") do |archive|
|
50
46
|
archive.add_file("later/return.txt", 0644) do |entry|
|
51
47
|
entry.write "say hi again"
|
52
48
|
end
|
@@ -56,7 +52,7 @@ module PuppetLibrary::Archive
|
|
56
52
|
end
|
57
53
|
|
58
54
|
it "fixes leading slash for adding files" do
|
59
|
-
buffer = Archiver.archive_dir(dir, "todo") do |archive|
|
55
|
+
buffer = Archiver.archive_dir(dir.path, "todo") do |archive|
|
60
56
|
archive.add_file("/later/return.txt", 0644) do |entry|
|
61
57
|
entry.write "say hi again"
|
62
58
|
end
|
data/spec/forge/cache_spec.rb
CHANGED
@@ -19,18 +19,24 @@ require 'spec_helper'
|
|
19
19
|
|
20
20
|
module PuppetLibrary::Forge
|
21
21
|
describe Cache do
|
22
|
-
let(:cache_dir) { Tempdir.
|
22
|
+
let(:cache_dir) { Tempdir.new("module-cache") }
|
23
23
|
let(:http_client) { double(PuppetLibrary::Http::HttpClient) }
|
24
24
|
let(:forge) { Cache.new("http://forge.example.com", cache_dir, http_client) }
|
25
25
|
|
26
|
-
after do
|
27
|
-
rm_rf cache_dir
|
28
|
-
end
|
29
|
-
|
30
26
|
it "is a proxy" do
|
31
27
|
expect(forge).to be_a Proxy
|
32
28
|
end
|
33
29
|
|
30
|
+
describe "#configure" do
|
31
|
+
it "exposes a configuration API" do
|
32
|
+
forge = Cache.configure do
|
33
|
+
url "http://example.com"
|
34
|
+
path cache_dir.path
|
35
|
+
end
|
36
|
+
expect(forge.instance_eval "@url").to eq "http://example.com"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
34
40
|
describe "#get_module_buffer" do
|
35
41
|
before do
|
36
42
|
allow(http_client).to receive(:get).
|
@@ -47,7 +53,7 @@ module PuppetLibrary::Forge
|
|
47
53
|
|
48
54
|
buffer = forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
|
49
55
|
|
50
|
-
downloaded_file = File.join(cache_dir, "puppetlabs-apache-1.0.0.tar.gz")
|
56
|
+
downloaded_file = File.join(cache_dir.path, "puppetlabs-apache-1.0.0.tar.gz")
|
51
57
|
expect(File.read downloaded_file).to eq "apache module"
|
52
58
|
expect(buffer.read).to eq "apache module"
|
53
59
|
end
|
@@ -55,7 +61,7 @@ module PuppetLibrary::Forge
|
|
55
61
|
|
56
62
|
context "the second time it's called" do
|
57
63
|
it "serves the cached module from the disk" do
|
58
|
-
cached_module = File.join(cache_dir, "puppetlabs-apache-1.0.0.tar.gz")
|
64
|
+
cached_module = File.join(cache_dir.path, "puppetlabs-apache-1.0.0.tar.gz")
|
59
65
|
File.open(cached_module, "w") do |file|
|
60
66
|
file.write "apache module"
|
61
67
|
end
|
@@ -20,43 +20,56 @@ module PuppetLibrary::Forge
|
|
20
20
|
describe Directory do
|
21
21
|
include ModuleSpecHelper
|
22
22
|
|
23
|
-
let(:module_dir) { Tempdir.
|
24
|
-
let(:
|
23
|
+
let(:module_dir) { Tempdir.new("module_dir") }
|
24
|
+
let(:forge) { Directory.new(module_dir) }
|
25
25
|
|
26
|
-
|
27
|
-
|
28
|
-
|
26
|
+
describe "#configure" do
|
27
|
+
it "exposes a configuration API" do
|
28
|
+
forge = Directory.configure do
|
29
|
+
path "."
|
30
|
+
end
|
31
|
+
expect(forge.instance_eval "@module_dir.path").to eq Dir.pwd
|
32
|
+
end
|
29
33
|
|
30
|
-
describe "#initialize" do
|
31
34
|
context "when the module directory doesn't exist" do
|
32
35
|
before do
|
33
|
-
rm_rf module_dir
|
36
|
+
rm_rf module_dir.path
|
34
37
|
end
|
35
38
|
|
36
39
|
it "raises an error" do
|
37
40
|
expect {
|
38
|
-
Directory.
|
39
|
-
|
41
|
+
Directory.configure do
|
42
|
+
path module_dir.path
|
43
|
+
end
|
44
|
+
}.to raise_error /No such file/
|
40
45
|
end
|
41
46
|
end
|
42
47
|
|
43
48
|
context "when the module directory isn't readable" do
|
44
49
|
before do
|
45
|
-
chmod 0400, module_dir
|
50
|
+
chmod 0400, module_dir.path
|
46
51
|
end
|
47
52
|
|
48
53
|
after do
|
49
|
-
chmod 0777, module_dir
|
54
|
+
chmod 0777, module_dir.path
|
50
55
|
end
|
51
56
|
|
52
57
|
it "raises an error" do
|
53
58
|
expect {
|
54
|
-
Directory.
|
59
|
+
Directory.configure do
|
60
|
+
path module_dir.path
|
61
|
+
end
|
55
62
|
}.to raise_error /Module directory .* isn't readable/
|
56
63
|
end
|
57
64
|
end
|
58
65
|
end
|
59
66
|
|
67
|
+
describe "#prime" do
|
68
|
+
it "does nothing" do
|
69
|
+
forge.prime
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
60
73
|
describe "#get_module" do
|
61
74
|
context "when the module archive exists" do
|
62
75
|
before do
|
@@ -64,7 +77,7 @@ module PuppetLibrary::Forge
|
|
64
77
|
end
|
65
78
|
|
66
79
|
it "returns a the module archive as a file buffer" do
|
67
|
-
buffer =
|
80
|
+
buffer = forge.get_module("puppetlabs", "apache", "1.0.0")
|
68
81
|
|
69
82
|
expect(buffer.path).to end_with("puppetlabs-apache-1.0.0.tar.gz")
|
70
83
|
end
|
@@ -72,7 +85,7 @@ module PuppetLibrary::Forge
|
|
72
85
|
|
73
86
|
context "when the module file doesn't exist" do
|
74
87
|
it "returns nil" do
|
75
|
-
buffer =
|
88
|
+
buffer = forge.get_module("puppetlabs", "noneixstant", "1.0.0")
|
76
89
|
|
77
90
|
expect(buffer).to be_nil
|
78
91
|
end
|
@@ -87,7 +100,7 @@ module PuppetLibrary::Forge
|
|
87
100
|
end
|
88
101
|
|
89
102
|
it "returns a the module archive as a file buffer" do
|
90
|
-
metadata =
|
103
|
+
metadata = forge.get_all_metadata
|
91
104
|
|
92
105
|
v1 = metadata.find {|m| m["version"] == "1.0.0" }
|
93
106
|
v2 = metadata.find {|m| m["version"] == "2.0.0" }
|
@@ -98,7 +111,7 @@ module PuppetLibrary::Forge
|
|
98
111
|
|
99
112
|
context "when no modules exist" do
|
100
113
|
it "returns an empty array" do
|
101
|
-
result =
|
114
|
+
result = forge.get_all_metadata
|
102
115
|
|
103
116
|
expect(result).to be_empty
|
104
117
|
end
|
@@ -108,7 +121,7 @@ module PuppetLibrary::Forge
|
|
108
121
|
describe "#get_metadata" do
|
109
122
|
context "when the module directory is empty" do
|
110
123
|
it "returns an empty array" do
|
111
|
-
metadata_list =
|
124
|
+
metadata_list = forge.get_metadata("puppetlabs", "apache")
|
112
125
|
expect(metadata_list).to be_empty
|
113
126
|
end
|
114
127
|
end
|
@@ -120,7 +133,7 @@ module PuppetLibrary::Forge
|
|
120
133
|
end
|
121
134
|
|
122
135
|
it "returns an array containing the module's versions' metadata" do
|
123
|
-
metadata_list =
|
136
|
+
metadata_list = forge.get_metadata("puppetlabs", "apache")
|
124
137
|
expect(metadata_list.size).to eq 2
|
125
138
|
metadata_list = metadata_list.sort_by {|m| m["version"] }
|
126
139
|
expect(metadata_list[0]["name"]).to eq "puppetlabs-apache"
|