puppet-library 0.0.2 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +0 -1
- data/README.md +23 -5
- data/Rakefile +18 -4
- data/TODO.yml +14 -3
- data/config.ru +7 -3
- data/lib/puppet_library.rb +5 -1
- data/lib/puppet_library/forge.rb +100 -0
- data/lib/puppet_library/http/cache.rb +61 -0
- data/lib/puppet_library/http/http_client.rb +35 -0
- data/lib/puppet_library/http/url.rb +27 -0
- data/lib/puppet_library/module_metadata.rb +9 -4
- data/lib/puppet_library/module_repo/proxy.rb +87 -0
- data/lib/puppet_library/puppet_library.rb +30 -20
- data/lib/puppet_library/server.rb +10 -67
- data/lib/puppet_library/util.rb +2 -2
- data/lib/puppet_library/version.rb +1 -1
- data/puppet-library.gemspec +3 -1
- data/spec/forge_spec.rb +147 -0
- data/spec/http/cache_spec.rb +63 -0
- data/spec/http/http_client_spec.rb +44 -0
- data/spec/http/url_spec.rb +39 -0
- data/spec/module_repo/directory_spec.rb +9 -5
- data/spec/module_repo/proxy_spec.rb +105 -0
- data/spec/module_spec_helper.rb +3 -1
- data/spec/puppet_library_spec.rb +64 -15
- data/spec/server_spec.rb +45 -77
- data/spec/spec_helper.rb +2 -0
- data/test/librarian_puppet_integration_test.rb +111 -0
- metadata +47 -2
@@ -0,0 +1,87 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# Puppet Library
|
3
|
+
# Copyright (C) 2014 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/http/http_client'
|
19
|
+
require 'puppet_library/http/cache'
|
20
|
+
require 'puppet_library/http/url'
|
21
|
+
|
22
|
+
module PuppetLibrary::ModuleRepo
|
23
|
+
class Proxy
|
24
|
+
def initialize(url, http_client = PuppetLibrary::Http::HttpClient.new, query_cache = PuppetLibrary::Http::Cache.new)
|
25
|
+
@url = PuppetLibrary::Http::Url.normalize(url)
|
26
|
+
@http_client = http_client
|
27
|
+
@query_cache = query_cache
|
28
|
+
end
|
29
|
+
|
30
|
+
def get_module(author, name, version)
|
31
|
+
version_info = get_module_version(author, name, version)
|
32
|
+
if version_info.nil?
|
33
|
+
nil
|
34
|
+
else
|
35
|
+
download_file(version_info["file"])
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def get_metadata(author, name)
|
40
|
+
module_versions = get_module_versions(author, name)
|
41
|
+
module_versions.map do |version_info|
|
42
|
+
{
|
43
|
+
"name" => "#{author}-#{name}",
|
44
|
+
"author" => author,
|
45
|
+
"version" => version_info["version"],
|
46
|
+
"dependencies" => version_info["dependencies"].map do |(dep_name, dep_spec)|
|
47
|
+
{ "name" => dep_name, "version_requirement" => dep_spec }
|
48
|
+
end
|
49
|
+
}
|
50
|
+
end
|
51
|
+
rescue OpenURI::HTTPError => http_error
|
52
|
+
return []
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def get_module_version(author, name, version)
|
57
|
+
module_versions = get_module_versions(author, name)
|
58
|
+
module_versions.find do |version_info|
|
59
|
+
version_info["version"] == version
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def get_module_versions(author, name)
|
64
|
+
versions = look_up_releases(author, name)
|
65
|
+
versions["#{author}/#{name}"]
|
66
|
+
end
|
67
|
+
|
68
|
+
def look_up_releases(author, name)
|
69
|
+
response = get("/api/v1/releases.json?module=#{author}/#{name}")
|
70
|
+
JSON.parse(response)
|
71
|
+
end
|
72
|
+
|
73
|
+
def download_file(file)
|
74
|
+
@http_client.download(url(file))
|
75
|
+
end
|
76
|
+
|
77
|
+
def get(relative_url)
|
78
|
+
@query_cache.get(relative_url) do
|
79
|
+
@http_client.get(url(relative_url))
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def url(relative_url)
|
84
|
+
@url + relative_url
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
# Puppet Library
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2014 drrb
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
@@ -16,6 +16,7 @@
|
|
16
16
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
17
17
|
|
18
18
|
require 'rack'
|
19
|
+
require 'puppet_library/forge'
|
19
20
|
require 'puppet_library/module_repo/directory'
|
20
21
|
require 'puppet_library/module_repo/multi'
|
21
22
|
|
@@ -41,19 +42,24 @@ module PuppetLibrary
|
|
41
42
|
option_parser = OptionParser.new do |opts|
|
42
43
|
opts.banner = "Usage: #{File.basename $0} [options]"
|
43
44
|
|
44
|
-
|
45
|
-
opts.on("-p", "--port [PORT]", "Port to listen on (defaults to #{options[:port]})") do |port|
|
45
|
+
opts.on("-p", "--port [PORT]", "Port to listen on (defaults to whatever Rack wants to use)") do |port|
|
46
46
|
options[:port] = port
|
47
47
|
end
|
48
48
|
|
49
|
-
|
50
|
-
|
49
|
+
opts.on("-s", "--server [SERVER]", "Server to use (defaults to whatever Rack wants to use)") do |server|
|
50
|
+
options[:server] = server
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on("-b", "--bind-host [HOSTNAME]", "Host name to bind to (defaults to whatever Rack wants to use)") do |hostname|
|
51
54
|
options[:hostname] = hostname
|
52
55
|
end
|
53
56
|
|
54
|
-
options[:
|
57
|
+
options[:repositories] = []
|
55
58
|
opts.on("-m", "--module-dir [DIR]", "Directory containing the modules (can be specified multiple times. Defaults to './modules')") do |module_dir|
|
56
|
-
options[:
|
59
|
+
options[:repositories] << [ModuleRepo::Directory, module_dir]
|
60
|
+
end
|
61
|
+
opts.on("-x", "--proxy [URL]", "Remote forge to proxy (can be specified multiple times)") do |url|
|
62
|
+
options[:repositories] << [ModuleRepo::Proxy, url]
|
57
63
|
end
|
58
64
|
end
|
59
65
|
begin
|
@@ -62,29 +68,32 @@ module PuppetLibrary
|
|
62
68
|
raise ExpectedError, parse_error.message + "\n" + option_parser.help
|
63
69
|
end
|
64
70
|
|
65
|
-
if options[:module_dirs].empty?
|
66
|
-
options[:module_dirs] << "./modules"
|
67
|
-
end
|
68
|
-
|
69
71
|
return options
|
70
72
|
end
|
71
73
|
|
72
74
|
def build_server(options)
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
75
|
+
if options[:repositories].empty?
|
76
|
+
options[:repositories] << [ ModuleRepo::Proxy, "http://forge.puppetlabs.com" ]
|
77
|
+
end
|
78
|
+
|
79
|
+
Server.set_up do |server|
|
80
|
+
options[:repositories].each do |(repo_type, config)|
|
81
|
+
subrepo = repo_type.new(config)
|
82
|
+
server.module_repo subrepo
|
83
|
+
end
|
77
84
|
end
|
78
|
-
Server.new(module_repo)
|
79
85
|
end
|
80
86
|
|
81
87
|
def announce_server_start(options)
|
88
|
+
options = options.clone
|
89
|
+
options.default = "default"
|
82
90
|
@log.puts "Starting Puppet Library server:"
|
83
91
|
@log.puts " |- Port: #{options[:port]}"
|
84
92
|
@log.puts " |- Host: #{options[:hostname]}"
|
85
|
-
@log.puts "
|
86
|
-
|
87
|
-
|
93
|
+
@log.puts " |- Server: #{options[:server]}"
|
94
|
+
@log.puts " `- Repositories:"
|
95
|
+
options[:repositories].each do |(repo_type, config)|
|
96
|
+
@log.puts " - #{repo_type}: #{config}"
|
88
97
|
end
|
89
98
|
end
|
90
99
|
|
@@ -92,7 +101,8 @@ module PuppetLibrary
|
|
92
101
|
Rack::Server.start(
|
93
102
|
:app => server,
|
94
103
|
:Host => options[:hostname],
|
95
|
-
:Port => options[:port]
|
104
|
+
:Port => options[:port],
|
105
|
+
:server => options[:server]
|
96
106
|
)
|
97
107
|
end
|
98
108
|
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
# Puppet Library
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2014 drrb
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
@@ -17,35 +17,19 @@
|
|
17
17
|
|
18
18
|
require 'sinatra/base'
|
19
19
|
|
20
|
+
require 'puppet_library/forge'
|
20
21
|
require 'puppet_library/module_metadata'
|
21
22
|
require 'puppet_library/module_repo/multi'
|
22
23
|
|
23
|
-
class Array
|
24
|
-
def deep_merge
|
25
|
-
inject({}) do |merged, map|
|
26
|
-
merged.deep_merge(map)
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
class Hash
|
32
|
-
def deep_merge(other)
|
33
|
-
merge(other) do |key, old_val, new_val|
|
34
|
-
if old_val.instance_of? Array
|
35
|
-
old_val + new_val
|
36
|
-
else
|
37
|
-
new_val
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
24
|
module PuppetLibrary
|
44
25
|
class Server < Sinatra::Base
|
26
|
+
def self.set_up(&config_block)
|
27
|
+
Server.new(Forge.configure(&config_block))
|
28
|
+
end
|
45
29
|
|
46
|
-
def initialize(
|
30
|
+
def initialize(forge)
|
47
31
|
super(nil)
|
48
|
-
@
|
32
|
+
@forge = forge
|
49
33
|
end
|
50
34
|
|
51
35
|
configure do
|
@@ -57,7 +41,7 @@ module PuppetLibrary
|
|
57
41
|
module_name = params[:module]
|
58
42
|
|
59
43
|
begin
|
60
|
-
get_module_metadata(author, module_name).to_json
|
44
|
+
@forge.get_module_metadata(author, module_name).to_json
|
61
45
|
rescue ModuleNotFound
|
62
46
|
status 410
|
63
47
|
{"error" => "Could not find module \"#{module_name}\""}.to_json
|
@@ -67,7 +51,7 @@ module PuppetLibrary
|
|
67
51
|
get "/api/v1/releases.json" do
|
68
52
|
author, module_name = params[:module].split "/"
|
69
53
|
begin
|
70
|
-
get_module_metadata_with_dependencies(author, module_name).to_json
|
54
|
+
@forge.get_module_metadata_with_dependencies(author, module_name).to_json
|
71
55
|
rescue ModuleNotFound
|
72
56
|
status 410
|
73
57
|
{"error" => "Module #{author}/#{module_name} not found"}.to_json
|
@@ -82,53 +66,12 @@ module PuppetLibrary
|
|
82
66
|
content_type "application/octet-stream"
|
83
67
|
|
84
68
|
begin
|
85
|
-
get_module_buffer(author, name, version).tap do
|
69
|
+
@forge.get_module_buffer(author, name, version).tap do
|
86
70
|
attachment "#{author}-#{name}-#{version}.tar.gz"
|
87
71
|
end
|
88
72
|
rescue ModuleNotFound
|
89
73
|
status 404
|
90
74
|
end
|
91
75
|
end
|
92
|
-
|
93
|
-
private
|
94
|
-
def get_module_metadata(author, name)
|
95
|
-
modules = get_metadata(author, name)
|
96
|
-
raise ModuleNotFound if modules.empty?
|
97
|
-
|
98
|
-
module_infos = modules.map { |m| m.to_info }
|
99
|
-
module_infos.deep_merge
|
100
|
-
end
|
101
|
-
|
102
|
-
def get_module_metadata_with_dependencies(author, name)
|
103
|
-
full_name = "#{author}/#{name}"
|
104
|
-
|
105
|
-
module_queue = []
|
106
|
-
modules_versions = {}
|
107
|
-
module_queue << full_name
|
108
|
-
until module_queue.empty?
|
109
|
-
module_full_name = module_queue.shift
|
110
|
-
already_added = modules_versions.include? module_full_name
|
111
|
-
unless already_added
|
112
|
-
author, module_name = module_full_name.split "/"
|
113
|
-
module_versions = get_metadata(author, module_name)
|
114
|
-
dependencies = module_versions.map {|v| v.dependency_names }.flatten
|
115
|
-
module_queue += dependencies
|
116
|
-
modules_versions[module_full_name] = module_versions.map { |v| v.to_version }
|
117
|
-
end
|
118
|
-
end
|
119
|
-
raise ModuleNotFound if modules_versions.values == [[]]
|
120
|
-
modules_versions
|
121
|
-
end
|
122
|
-
|
123
|
-
def get_module_buffer(author, name, version)
|
124
|
-
@repo.get_module(author, name, version) or raise ModuleNotFound
|
125
|
-
end
|
126
|
-
|
127
|
-
def get_metadata(author, module_name)
|
128
|
-
@repo.get_metadata(author, module_name).map {|metadata| ModuleMetadata.new(metadata)}
|
129
|
-
end
|
130
76
|
end
|
131
77
|
end
|
132
|
-
|
133
|
-
class ModuleNotFound < Exception
|
134
|
-
end
|
data/lib/puppet_library/util.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
# Puppet Library
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2014 drrb
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
@@ -23,7 +23,7 @@ class Array
|
|
23
23
|
attribute = yield(element)
|
24
24
|
is_duplicate = attr_to_element.include? attribute
|
25
25
|
unless is_duplicate
|
26
|
-
attr_to_element[
|
26
|
+
attr_to_element[attribute] = element
|
27
27
|
end
|
28
28
|
!is_duplicate
|
29
29
|
end
|
data/puppet-library.gemspec
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# -*- encoding: utf-8 -*-
|
2
2
|
# Puppet Library
|
3
|
-
# Copyright (C)
|
3
|
+
# Copyright (C) 2014 drrb
|
4
4
|
#
|
5
5
|
# This program is free software: you can redistribute it and/or modify
|
6
6
|
# it under the terms of the GNU General Public License as published by
|
@@ -41,8 +41,10 @@ Gem::Specification.new do |spec|
|
|
41
41
|
|
42
42
|
spec.add_development_dependency "bundler", "~> 1.3"
|
43
43
|
spec.add_development_dependency "coveralls"
|
44
|
+
spec.add_development_dependency "librarian-puppet"
|
44
45
|
spec.add_development_dependency "mime-types", "< 2"
|
45
46
|
spec.add_development_dependency "pry"
|
47
|
+
spec.add_development_dependency "puppet"
|
46
48
|
spec.add_development_dependency "rack-test"
|
47
49
|
spec.add_development_dependency "rake"
|
48
50
|
spec.add_development_dependency "rspec"
|
data/spec/forge_spec.rb
ADDED
@@ -0,0 +1,147 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
# Puppet Library
|
3
|
+
# Copyright (C) 2014 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 'spec_helper'
|
19
|
+
|
20
|
+
module PuppetLibrary
|
21
|
+
describe Forge do
|
22
|
+
let(:forge) { Forge.new(module_repo) }
|
23
|
+
let(:module_repo) { double('module_repo') }
|
24
|
+
|
25
|
+
describe "#get_module_buffer" do
|
26
|
+
context "module version not found" do
|
27
|
+
it "raises an error" do
|
28
|
+
expect(module_repo).to receive(:get_module).with("puppetlabs", "apache", "1.0.0").and_return(nil)
|
29
|
+
|
30
|
+
expect {
|
31
|
+
forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
|
32
|
+
}.to raise_error ModuleNotFound
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context "when the module is found" do
|
37
|
+
it "returns a buffer containing the module archive" do
|
38
|
+
file_buffer = "module content"
|
39
|
+
expect(module_repo).to receive(:get_module).with("puppetlabs", "apache", "1.0.0").and_return(file_buffer)
|
40
|
+
|
41
|
+
result = forge.get_module_buffer("puppetlabs", "apache", "1.0.0")
|
42
|
+
expect(result).to eq file_buffer
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
describe "#get_module_metadata" do
|
48
|
+
context "when no modules found" do
|
49
|
+
it "raises an error" do
|
50
|
+
expect(module_repo).to receive(:get_metadata).with("nonexistant", "nonexistant").and_return([])
|
51
|
+
|
52
|
+
expect {
|
53
|
+
forge.get_module_metadata("nonexistant", "nonexistant")
|
54
|
+
}.to raise_error ModuleNotFound
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context "when module versions found" do
|
59
|
+
it "returns metadata for all versions" do
|
60
|
+
metadata = [ {
|
61
|
+
"author" => "puppetlabs",
|
62
|
+
"name" => "puppetlabs-apache",
|
63
|
+
"description" => "Apache module",
|
64
|
+
"version" => "1.0.0"
|
65
|
+
}, {
|
66
|
+
"author" => "puppetlabs",
|
67
|
+
"name" => "puppetlabs-apache",
|
68
|
+
"description" => "Apache module",
|
69
|
+
"version" => "1.1.0"
|
70
|
+
} ]
|
71
|
+
expect(module_repo).to receive(:get_metadata).with("puppetlabs", "apache").and_return(metadata)
|
72
|
+
|
73
|
+
metadata = forge.get_module_metadata("puppetlabs", "apache")
|
74
|
+
|
75
|
+
expect(metadata["author"]).to eq "puppetlabs"
|
76
|
+
expect(metadata["full_name"]).to eq "puppetlabs/apache"
|
77
|
+
expect(metadata["name"]).to eq "apache"
|
78
|
+
expect(metadata["desc"]).to eq "Apache module"
|
79
|
+
expect(metadata["releases"]).to eq [
|
80
|
+
{"version" => "1.0.0"},
|
81
|
+
{"version" => "1.1.0"}
|
82
|
+
]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "#get_module_metadata_with_dependencies" do
|
88
|
+
context "when no module versions found" do
|
89
|
+
it "raises an error" do
|
90
|
+
expect(module_repo).to receive(:get_metadata).with("nonexistant", "nonexistant").and_return([])
|
91
|
+
|
92
|
+
expect {
|
93
|
+
forge.get_module_metadata_with_dependencies("nonexistant", "nonexistant")
|
94
|
+
}.to raise_error ModuleNotFound
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context "when module versions found" do
|
99
|
+
it "returns metadata for module and dependencies" do
|
100
|
+
apache_metadata = [ {
|
101
|
+
"author" => "puppetlabs",
|
102
|
+
"name" => "puppetlabs-apache",
|
103
|
+
"description" => "Apache module",
|
104
|
+
"version" => "1.0.0",
|
105
|
+
"dependencies" => [
|
106
|
+
{ "name" => "puppetlabs/stdlib", "version_requirement" => ">= 2.4.0" },
|
107
|
+
{ "name" => "puppetlabs/concat", "version_requirement" => ">= 1.0.0" }
|
108
|
+
]
|
109
|
+
}, {
|
110
|
+
"author" => "puppetlabs",
|
111
|
+
"name" => "puppetlabs-apache",
|
112
|
+
"description" => "Apache module",
|
113
|
+
"version" => "1.1.0",
|
114
|
+
"dependencies" => [
|
115
|
+
{ "name" => "puppetlabs/stdlib", "version_requirement" => ">= 2.4.0" },
|
116
|
+
{ "name" => "puppetlabs/concat", "version_requirement" => ">= 1.0.0" }
|
117
|
+
]
|
118
|
+
} ]
|
119
|
+
stdlib_metadata = [ {
|
120
|
+
"author" => "puppetlabs",
|
121
|
+
"name" => "puppetlabs-stdlib",
|
122
|
+
"description" => "Stdlib module",
|
123
|
+
"version" => "2.0.0",
|
124
|
+
"dependencies" => [ ]
|
125
|
+
} ]
|
126
|
+
concat_metadata = [ {
|
127
|
+
"author" => "puppetlabs",
|
128
|
+
"name" => "puppetlabs-concat",
|
129
|
+
"description" => "Concat module",
|
130
|
+
"version" => "1.0.0",
|
131
|
+
"dependencies" => [ ]
|
132
|
+
} ]
|
133
|
+
expect(module_repo).to receive(:get_metadata).with("puppetlabs", "apache").and_return(apache_metadata)
|
134
|
+
expect(module_repo).to receive(:get_metadata).with("puppetlabs", "stdlib").and_return(stdlib_metadata)
|
135
|
+
expect(module_repo).to receive(:get_metadata).with("puppetlabs", "concat").and_return(concat_metadata)
|
136
|
+
|
137
|
+
result = forge.get_module_metadata_with_dependencies("puppetlabs", "apache")
|
138
|
+
expect(result.keys.sort).to eq(["puppetlabs/apache", "puppetlabs/concat", "puppetlabs/stdlib"])
|
139
|
+
expect(result["puppetlabs/apache"].size).to eq(2)
|
140
|
+
expect(result["puppetlabs/apache"][0]["file"]).to eq("/modules/puppetlabs-apache-1.0.0.tar.gz")
|
141
|
+
expect(result["puppetlabs/apache"][0]["version"]).to eq("1.0.0")
|
142
|
+
expect(result["puppetlabs/apache"][0]["version"]).to eq("1.0.0")
|
143
|
+
end
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|