puppet-library 0.8.0 → 0.9.0

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