puppet-library 0.8.0 → 0.9.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.
@@ -0,0 +1,64 @@
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 'spec_helper'
18
+
19
+ module PuppetLibrary::Archive
20
+ describe ArchiveReader do
21
+ let :reader do
22
+ ArchiveReader.new(archive)
23
+ end
24
+
25
+ let :archive do
26
+ dir = Tempdir.create("zipping")
27
+ archive = File.join(dir, "archive.tgz")
28
+ write_tar_gzip!(archive) do |zip|
29
+ zip.add_file("arrive.txt", 0644) { |entry| entry.write "say hello" }
30
+ zip.add_file("later/depart.txt", 0644) { |entry| entry.write "say bye" }
31
+ end
32
+ archive
33
+ end
34
+
35
+ def write_tar_gzip!(file_name)
36
+ tar = StringIO.new
37
+
38
+ Gem::Package::TarWriter.new(tar) do |writer|
39
+ yield(writer)
40
+ end
41
+ tar.seek(0)
42
+
43
+ gz = Zlib::GzipWriter.new(File.new(file_name, 'wb'))
44
+ gz.write(tar.read)
45
+ tar.close
46
+ gz.close
47
+ end
48
+
49
+ describe "#read_entry" do
50
+ it "reads the first entry matched by the regex" do
51
+ arrival_task = reader.read_entry /arrive/
52
+ expect(arrival_task).to eq "say hello"
53
+ end
54
+
55
+ context "when the entry isn't found" do
56
+ it "raises an error" do
57
+ expect {
58
+ reader.read_entry /xxx/
59
+ }.to raise_error /Couldn't find entry/
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,66 @@
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 'spec_helper'
18
+
19
+ module PuppetLibrary::Archive
20
+ describe Archiver do
21
+ describe "#archive_dir" do
22
+ let(:dir) { Tempdir.create("tozip") }
23
+
24
+ def write_file!(filename, content)
25
+ path = File.join(dir, filename)
26
+ FileUtils.mkdir_p(File.dirname(path))
27
+ File.open(path, "w") do |file|
28
+ file.write content
29
+ end
30
+ end
31
+
32
+ before do
33
+ write_file! "arrive.txt", "say hello"
34
+ write_file! "later/depart.txt", "say bye"
35
+ end
36
+
37
+ it "tars and gzips a directory and its contents" do
38
+ buffer = Archiver.archive_dir(dir, "todo")
39
+
40
+ expect(buffer).to be_tgz_with "todo/arrive.txt", "say hello"
41
+ expect(buffer).to be_tgz_with "todo/later/depart.txt", "say bye"
42
+ end
43
+
44
+ it "allows you to inject files from a block" do
45
+ buffer = Archiver.archive_dir(dir, "todo") do |archive|
46
+ archive.add_file("later/return.txt", 0644) do |entry|
47
+ entry.write "say hi again"
48
+ end
49
+ end
50
+
51
+ expect(buffer).to be_tgz_with "todo/later/return.txt", "say hi again"
52
+ end
53
+
54
+ it "fixes leading slash for adding files" do
55
+ buffer = Archiver.archive_dir(dir, "todo") do |archive|
56
+ archive.add_file("/later/return.txt", 0644) do |entry|
57
+ entry.write "say hi again"
58
+ end
59
+ end
60
+
61
+ expect(buffer).to be_tgz_with "todo/later/return.txt", "say hi again"
62
+ end
63
+ end
64
+ end
65
+ end
66
+
@@ -0,0 +1,133 @@
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 'spec_helper'
18
+
19
+ module PuppetLibrary::Forge
20
+ describe Source do
21
+ let(:module_dir) { Tempdir.create("module_dir") }
22
+ let(:modulefile_path) { File.join(module_dir, "Modulefile") }
23
+ let(:forge) { Source.new(module_dir) }
24
+
25
+ before do
26
+ set_module! "puppetlabs", "apache", "1.0.0"
27
+ add_module_dependency! "puppetlabs", "stdlib", ">= 2.4.0"
28
+ add_module_dependency! "puppetlabs", "concat", ">= 1.0.1"
29
+ end
30
+
31
+ after do
32
+ rm_rf module_dir
33
+ end
34
+
35
+ def set_module!(author, name, version)
36
+ File.open(modulefile_path, "w") do |modulefile|
37
+ modulefile.puts <<-EOF
38
+ name '#{author}-#{name}'
39
+ version '#{version}'
40
+ author '#{author}'
41
+ description '#{author} #{name} module, version #{version}'
42
+ EOF
43
+ end
44
+ end
45
+
46
+ def add_module_dependency!(author, name, spec)
47
+ File.open(modulefile_path, "a") do |modulefile|
48
+ modulefile.puts <<-EOF
49
+ dependency "#{author}/#{name}", "#{spec}"
50
+ EOF
51
+ end
52
+ end
53
+
54
+ describe "#initialize" do
55
+ context "when the module directory doesn't exist" do
56
+ before do
57
+ rm_rf module_dir
58
+ end
59
+
60
+ it "raises an error" do
61
+ expect {
62
+ Source.new(module_dir)
63
+ }.to raise_error /Module directory .* doesn't exist/
64
+ end
65
+ end
66
+
67
+ context "when the module directory isn't readable" do
68
+ before do
69
+ chmod 0400, module_dir
70
+ end
71
+
72
+ it "raises an error" do
73
+ expect {
74
+ Source.new(module_dir)
75
+ }.to raise_error /Module directory .* isn't readable/
76
+ end
77
+ end
78
+ end
79
+
80
+ describe "#get_module" do
81
+ context "when the requested module doesn't match the source module" do
82
+ it "returns nil" do
83
+ expect(forge.get_module("puppetlabs", "apache", "0.9.0")).to be_nil
84
+ expect(forge.get_module("puppetlabs", "stdlib", "1.0.0")).to be_nil
85
+ end
86
+ end
87
+
88
+ context "when the source module is requested" do
89
+ it "returns a buffer of the packaged module" do
90
+ buffer = forge.get_module("puppetlabs", "apache", "1.0.0")
91
+
92
+ expect(buffer).to be_tgz_with(/Modulefile/, /puppetlabs-apache/)
93
+ end
94
+
95
+ it "generates a metadata file in the packaged application" do
96
+ buffer = forge.get_module("puppetlabs", "apache", "1.0.0")
97
+
98
+ expect(buffer).to be_tgz_with(/metadata.json/, /puppetlabs-apache/)
99
+ end
100
+ end
101
+ end
102
+
103
+ describe "#get_metadata" do
104
+ context "when the requested module doesn't match the source module" do
105
+ it "returns an empty list" do
106
+ expect(forge.get_metadata("puppetlabs", "somethingelse")).to be_empty
107
+ end
108
+ end
109
+
110
+ context "when the requested module is the source module" do
111
+ it "returns an empty list" do
112
+ metadata = forge.get_metadata("puppetlabs", "apache").first
113
+
114
+ expect(metadata["name"]).to eq "puppetlabs-apache"
115
+ expect(metadata["version"]).to eq "1.0.0"
116
+ expect(metadata["author"]).to eq "puppetlabs"
117
+ expect(metadata["description"]).to eq "puppetlabs apache module, version 1.0.0"
118
+ expect(metadata["dependencies"]).to eq [
119
+ { "name" => "puppetlabs/stdlib", "version_requirement" => ">= 2.4.0" },
120
+ { "name" => "puppetlabs/concat", "version_requirement" => ">= 1.0.1" }
121
+ ]
122
+ end
123
+ end
124
+ end
125
+
126
+ describe "#get_all_metadata" do
127
+ it "calls #get_metadata with the appropriate author and name" do
128
+ expect(forge).to receive(:get_metadata).with("puppetlabs", "apache").and_return("metadata")
129
+ expect(forge.get_all_metadata).to eq "metadata"
130
+ end
131
+ end
132
+ end
133
+ end
@@ -62,4 +62,10 @@ module ModuleSpecHelper
62
62
  writer = ModuleWriter.new(module_dir)
63
63
  writer.write_module(author, name, version, &block)
64
64
  end
65
+
66
+ def add_file(file, content)
67
+ File.open(File.join(module_dir, file), "w") do |f|
68
+ f.write content
69
+ end
70
+ end
65
71
  end
@@ -189,6 +189,20 @@ module PuppetLibrary
189
189
  end
190
190
  end
191
191
 
192
+ context "when using --source-dir option" do
193
+ it "adds a source forge to the server for each source directory" do
194
+ source_forge_1 = double("source_forge_1")
195
+ source_forge_2 = double("source_forge_2")
196
+ expect(Forge::Source).to receive(:new).with("dir1").and_return(source_forge_1)
197
+ expect(Forge::Source).to receive(:new).with("dir2").and_return(source_forge_2)
198
+ expect(forge).to receive(:add_forge).with(source_forge_1)
199
+ expect(forge).to receive(:add_forge).with(source_forge_2)
200
+ expect(Rack::Server).to receive(:start).with(default_options)
201
+
202
+ library.go(["--source-dir", "dir1", "--source-dir", "dir2"])
203
+ end
204
+ end
205
+
192
206
  context "when no proxy URLs or module directories specified" do
193
207
  it "proxies the Puppet Forge" do
194
208
  proxy = double("proxy")
@@ -0,0 +1,106 @@
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 'spec_helper'
18
+
19
+ module PuppetLibrary::PuppetModule
20
+ describe Modulefile do
21
+ let(:modulefile) { Tempfile.new("Modulefile") }
22
+
23
+ def write_modulefile(content)
24
+ File.open(modulefile.path, "w") do |f|
25
+ f.write content
26
+ end
27
+ end
28
+
29
+ before do
30
+ write_modulefile <<-EOF
31
+ name 'joe-ficticious'
32
+ version '1.2.3'
33
+ source 'git://example.com/joe/puppet-ficticious.git'
34
+ author 'joe'
35
+ license 'Apache 2.0'
36
+ summary 'Example module'
37
+ description 'Module for use in a test'
38
+ project_page 'https://example.com/joe/puppet-apache'
39
+
40
+ dependency 'example/standard', '>= 2.3.4'
41
+ dependency 'example/other', '>= 5.6.7'
42
+ EOF
43
+ end
44
+
45
+ after do
46
+ modulefile.unlink
47
+ end
48
+
49
+ describe "#read" do
50
+ let(:metadata) { Modulefile.read(modulefile.path) }
51
+
52
+ it "parses the name" do
53
+ expect(metadata.get_name).to eq "joe-ficticious"
54
+ end
55
+
56
+ it "parses the version" do
57
+ expect(metadata.get_version).to eq "1.2.3"
58
+ end
59
+
60
+ it "parses the author" do
61
+ expect(metadata.get_author).to eq "joe"
62
+ end
63
+
64
+ it "parses the source URL" do
65
+ expect(metadata.get_source).to eq "git://example.com/joe/puppet-ficticious.git"
66
+ end
67
+
68
+ it "parses the summary" do
69
+ expect(metadata.get_summary).to eq "Example module"
70
+ end
71
+
72
+ it "parses the description" do
73
+ expect(metadata.get_description).to eq "Module for use in a test"
74
+ end
75
+
76
+ it "parses the project URL" do
77
+ expect(metadata.get_project_page).to eq "https://example.com/joe/puppet-apache"
78
+ end
79
+
80
+ it "parses the license name" do
81
+ expect(metadata.get_license).to eq "Apache 2.0"
82
+ end
83
+
84
+
85
+ it "parses the dependencies" do
86
+ expect(metadata.get_dependencies).to eq [
87
+ { "name" => "example/standard", "version_requirement" => '>= 2.3.4' },
88
+ { "name" => "example/other", "version_requirement" => '>= 5.6.7' }
89
+ ]
90
+ end
91
+
92
+ context "when a bad value is configured" do
93
+ it "logs the bad config, but doesn't blow up" do
94
+ write_modulefile <<-EOF
95
+ name 'joe-ficticious'
96
+ version '1.2.3'
97
+ rating '10'
98
+ EOF
99
+ expect(Modulefile).to receive(:log).with(/rating/)
100
+ Modulefile.read(modulefile.path)
101
+ end
102
+ end
103
+ end
104
+ end
105
+ end
106
+
data/spec/spec_helper.rb CHANGED
@@ -39,3 +39,35 @@ class Tempdir
39
39
  FileUtils.mkdir @path
40
40
  end
41
41
  end
42
+
43
+ class Tgz
44
+ def initialize(buffer)
45
+ @buffer = buffer
46
+ end
47
+
48
+ def read(entry_name)
49
+ @buffer.rewind
50
+ tar = Gem::Package::TarReader.new(Zlib::GzipReader.wrap(@buffer))
51
+ tar.rewind
52
+ entry = tar.find do |e|
53
+ if Regexp === entry_name
54
+ e.full_name =~ entry_name
55
+ else
56
+ e.full_name == entry_name
57
+ end
58
+ end
59
+ raise "No entry matching #{entry_name} found" if entry.nil?
60
+ entry.read
61
+ end
62
+ end
63
+
64
+ RSpec::Matchers.define :be_tgz_with do |expected_file_name, expected_content|
65
+ match do |buffer|
66
+ file_content = Tgz.new(buffer).read expected_file_name
67
+ if Regexp === expected_content
68
+ file_content =~ expected_content
69
+ else
70
+ file_content == expected_content
71
+ end
72
+ end
73
+ end
@@ -93,13 +93,13 @@ module PuppetLibrary
93
93
  mod 'puppetlabs/apache'
94
94
  EOF
95
95
 
96
- # Install modules through the proxy
96
+ # Install modules
97
97
  system "librarian-puppet install" or fail "call to puppet-library failed"
98
98
  expect("apache").to be_installed
99
99
  expect("concat").to be_installed
100
100
  expect("stdlib").to be_installed
101
101
 
102
- # Search through the proxy
102
+ # Search
103
103
  search_results = JSON.parse(open("http://localhost:9004/modules.json").read)
104
104
  found_modules = Hash[search_results.map do |result|
105
105
  [ result["full_name"], result["version"] ]
@@ -110,6 +110,79 @@ module PuppetLibrary
110
110
  end
111
111
  end
112
112
 
113
+ describe "source forge" do
114
+ include ModuleSpecHelper
115
+
116
+ let(:module_dir) { Tempdir.create("module_dir") }
117
+ let(:project_dir) { Tempdir.create("project_dir") }
118
+ let(:start_dir) { pwd }
119
+ let(:source_forge) { Forge::Source.new(module_dir) }
120
+ let(:source_server) do
121
+ Server.set_up do |server|
122
+ server.forge source_forge
123
+ end
124
+ end
125
+ let(:source_rack_server) do
126
+ Rack::Server.new(
127
+ :app => source_server,
128
+ :Host => "localhost",
129
+ :Port => 9005,
130
+ :server => "webrick"
131
+ )
132
+ end
133
+ let(:source_server_runner) do
134
+ Thread.new do
135
+ source_rack_server.start
136
+ end
137
+ end
138
+
139
+ before do
140
+ # Initialize to catch wiring errors
141
+ source_rack_server
142
+
143
+ # Start the servers
144
+ source_server_runner
145
+ start_dir
146
+ cd project_dir
147
+ end
148
+
149
+ after do
150
+ rm_rf module_dir
151
+ rm_rf project_dir
152
+ cd start_dir
153
+ end
154
+
155
+ it "queries, downloads and searches from a directory" do
156
+ add_file "Modulefile", <<-EOF
157
+ name 'puppetlabs-ficticious'
158
+ version '0.2.0'
159
+ author 'puppetlabs'
160
+ description 'Fake module'
161
+ EOF
162
+
163
+ write_puppetfile <<-EOF
164
+ forge 'http://localhost:9005'
165
+ mod 'puppetlabs/ficticious'
166
+ EOF
167
+
168
+ # Install modules
169
+ system "librarian-puppet install" or fail "call to puppet-library failed"
170
+ expect("ficticious").to be_installed
171
+
172
+ # Search
173
+ search_results = JSON.parse(open("http://localhost:9005/modules.json").read)
174
+ found_modules = Hash[search_results.map do |result|
175
+ [ result["full_name"], result["version"] ]
176
+ end]
177
+ expect(found_modules["puppetlabs/ficticious"]).to eq "0.2.0"
178
+
179
+ # Download
180
+ archive = open("http://localhost:9005/modules/puppetlabs-ficticious-0.2.0.tar.gz")
181
+ expect(archive).to be_tgz_with /Modulefile/, /puppetlabs-ficticious/
182
+ expect(archive).to be_tgz_with /metadata.json/, /puppetlabs-ficticious/
183
+ end
184
+ end
185
+
113
186
  describe "offline proxy", :no_1_8 => true do
114
187
  include ModuleSpecHelper
115
188