librarian-puppet 1.5.0 → 2.0.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/README.md +1 -21
- data/lib/librarian/puppet/action.rb +0 -1
- data/lib/librarian/puppet/cli.rb +0 -10
- data/lib/librarian/puppet/dsl.rb +19 -24
- data/lib/librarian/puppet/environment.rb +1 -9
- data/lib/librarian/puppet/extension.rb +220 -0
- data/lib/librarian/puppet/lockfile/parser.rb +55 -0
- data/lib/librarian/puppet/requirement.rb +35 -0
- data/lib/librarian/puppet/source.rb +1 -0
- data/lib/librarian/puppet/source/forge.rb +10 -18
- data/lib/librarian/puppet/source/forge/repo_v1.rb +25 -4
- data/lib/librarian/puppet/source/local.rb +9 -10
- data/lib/librarian/puppet/templates/Puppetfile +1 -1
- data/lib/librarian/puppet/util.rb +1 -1
- data/lib/librarian/puppet/version.rb +1 -1
- metadata +35 -36
- data/lib/librarian/puppet/action/resolve.rb +0 -19
- data/lib/librarian/puppet/dependency.rb +0 -18
- data/lib/librarian/puppet/lockfile.rb +0 -39
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 83e9713858b646cdf2e4a3bc35a7a4b10d381aed
|
4
|
+
data.tar.gz: ea2912415c6e31b96d0b466e4d3cf7d646a37955
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e03c1bf94ab9f59051f16a69aa9a17233a40b73c377e23501ffab3e4921694416ebdf152bca5a06912d0c2e388fcd54879471131e4c96f66f35470b59121194c
|
7
|
+
data.tar.gz: 0adb68c0f41531740e2e52a604f788b96f0eb55477e6d0a973ab39900849f09d3b81637675bac04bbcc14e6c719ca712d3ad89c77e269381748eaf60a72edad6
|
data/README.md
CHANGED
@@ -7,13 +7,12 @@
|
|
7
7
|
Librarian-puppet is a bundler for your puppet infrastructure. You can use
|
8
8
|
librarian-puppet to manage the puppet modules your infrastructure depends on,
|
9
9
|
whether the modules come from the [Puppet Forge](https://forge.puppetlabs.com/),
|
10
|
-
Git repositories or just a path.
|
10
|
+
Git repositories or a just a path.
|
11
11
|
|
12
12
|
* Librarian-puppet can reuse the dependencies listed in your `Modulefile` or `metadata.json`
|
13
13
|
* Forge modules can be installed from [Puppetlabs Forge](https://forge.puppetlabs.com/) or an internal Forge such as [Pulp](http://www.pulpproject.org/)
|
14
14
|
* Git modules can be installed from a branch, tag or specific commit, optionally using a path inside the repository
|
15
15
|
* Modules can be installed from GitHub using tarballs, without needing Git installed
|
16
|
-
* Modules can be installed from a filesystem path
|
17
16
|
* Module dependencies are resolved transitively without needing to list all the modules explicitly
|
18
17
|
|
19
18
|
|
@@ -70,10 +69,6 @@ as if the Puppetfile contained
|
|
70
69
|
mod 'puppetlabs-apache', '0.6.0',
|
71
70
|
:github_tarball => 'puppetlabs/puppetlabs-apache'
|
72
71
|
|
73
|
-
mod 'acme-mymodule', :path => './some_folder'
|
74
|
-
|
75
|
-
exclusion 'acme-bad_module'
|
76
|
-
|
77
72
|
|
78
73
|
### Recursive module dependency resolution
|
79
74
|
|
@@ -139,21 +134,6 @@ module subdirectory.
|
|
139
134
|
Our puppet infrastructure repository depends on the `apt` module, which we have
|
140
135
|
stored as a directory under our `puppet-modules` git repos.
|
141
136
|
|
142
|
-
mod 'puppetlabs-apache', '0.6.0',
|
143
|
-
:github_tarball => 'puppetlabs/puppetlabs-apache'
|
144
|
-
|
145
|
-
Our puppet infrastructure repository depends on the `puppetlabs-apache` module,
|
146
|
-
to be downloaded from GitHub tarball.
|
147
|
-
|
148
|
-
mod 'acme-mymodule', :path => './some_folder'
|
149
|
-
|
150
|
-
Our puppet infrastructure repository depends on the `acme-mymodule` module,
|
151
|
-
which is already in the filesystem.
|
152
|
-
|
153
|
-
exclusion 'acme-bad_module'
|
154
|
-
|
155
|
-
Exclude the module `acme-bad_module` from resolution and installation.
|
156
|
-
|
157
137
|
## How to Use
|
158
138
|
|
159
139
|
Install librarian-puppet:
|
data/lib/librarian/puppet/cli.rb
CHANGED
@@ -7,7 +7,6 @@ require 'librarian/puppet/action'
|
|
7
7
|
module Librarian
|
8
8
|
module Puppet
|
9
9
|
class Cli < Librarian::Cli
|
10
|
-
include Librarian::Puppet::Util
|
11
10
|
|
12
11
|
module Particularity
|
13
12
|
def root_module
|
@@ -70,12 +69,6 @@ module Librarian
|
|
70
69
|
install!
|
71
70
|
end
|
72
71
|
|
73
|
-
# only used to replace / to - in the module names
|
74
|
-
def update(*names)
|
75
|
-
warn("Usage of module/name is deprecated, use module-name") if names.any? {|n| n.include?("/")}
|
76
|
-
super(*names.map{|n| normalize_name(n)})
|
77
|
-
end
|
78
|
-
|
79
72
|
desc "package", "Cache the puppet modules in vendor/puppet/cache."
|
80
73
|
option "quiet", :type => :boolean, :default => false
|
81
74
|
option "verbose", :type => :boolean, :default => false
|
@@ -100,9 +93,6 @@ module Librarian
|
|
100
93
|
def install!(options = { })
|
101
94
|
Action::Install.new(environment, options).run
|
102
95
|
end
|
103
|
-
def resolve!(options = { })
|
104
|
-
Action::Resolve.new(environment, options).run
|
105
|
-
end
|
106
96
|
end
|
107
97
|
end
|
108
98
|
end
|
data/lib/librarian/puppet/dsl.rb
CHANGED
@@ -1,14 +1,11 @@
|
|
1
1
|
require 'librarian/dsl'
|
2
2
|
require 'librarian/dsl/target'
|
3
3
|
require 'librarian/puppet/source'
|
4
|
-
require 'librarian/puppet/dependency'
|
5
4
|
|
6
5
|
module Librarian
|
7
6
|
module Puppet
|
8
7
|
class Dsl < Librarian::Dsl
|
9
8
|
|
10
|
-
FORGE_URL = "http://forge.puppetlabs.com"
|
11
|
-
|
12
9
|
dependency :mod
|
13
10
|
|
14
11
|
source :forge => Source::Forge
|
@@ -16,25 +13,28 @@ module Librarian
|
|
16
13
|
source :path => Source::Path
|
17
14
|
source :github_tarball => Source::GitHubTarball
|
18
15
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
16
|
+
# copied from Librarian::Dsl to use our own Receiver
|
17
|
+
def run(specfile = nil, sources = [])
|
18
|
+
specfile, sources = nil, specfile if specfile.kind_of?(Array) && sources.empty?
|
19
|
+
|
20
|
+
if specfile.kind_of?(Pathname) and !File.exists?(specfile)
|
21
|
+
debug { "Specfile not found, using defaults: #{specfile}" }
|
22
|
+
specfile = Proc.new do
|
23
|
+
forge "https://forgeapi.puppetlabs.com"
|
24
|
+
metadata
|
25
|
+
end
|
23
26
|
end
|
24
|
-
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
28
|
+
Target.new(self).tap do |target|
|
29
|
+
target.precache_sources(sources)
|
30
|
+
debug_named_source_cache("Pre-Cached Sources", target)
|
29
31
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
Librarian::Puppet::Source::Forge.default = default_forge || Librarian::Puppet::Source::Forge.from_lock_options(environment, :remote => FORGE_URL)
|
34
|
-
end
|
32
|
+
specfile ||= Proc.new if block_given?
|
33
|
+
receiver = Receiver.new(target)
|
34
|
+
receiver.run(specfile)
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
debug_named_source_cache("Post-Cached Sources", target)
|
37
|
+
end.to_spec
|
38
38
|
end
|
39
39
|
|
40
40
|
class Receiver < Librarian::Dsl::Receiver
|
@@ -70,12 +70,7 @@ module Librarian
|
|
70
70
|
raise Error, msg
|
71
71
|
end
|
72
72
|
end
|
73
|
-
|
74
|
-
json = JSON.parse(File.read(f))
|
75
|
-
rescue JSON::ParserError => e
|
76
|
-
raise Error, "Unable to parse json file #{f}: #{e}"
|
77
|
-
end
|
78
|
-
dependencyList = json['dependencies']
|
73
|
+
dependencyList = JSON.parse(File.read(f))['dependencies']
|
79
74
|
dependencyList.each do |d|
|
80
75
|
mod(d['name'], d['version_requirement'])
|
81
76
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require "librarian/environment"
|
2
2
|
require "librarian/puppet/dsl"
|
3
3
|
require "librarian/puppet/source"
|
4
|
-
require "librarian/puppet/lockfile"
|
4
|
+
require "librarian/puppet/lockfile/parser"
|
5
5
|
|
6
6
|
module Librarian
|
7
7
|
module Puppet
|
@@ -11,14 +11,6 @@ module Librarian
|
|
11
11
|
"puppet"
|
12
12
|
end
|
13
13
|
|
14
|
-
def lockfile
|
15
|
-
Lockfile.new(self, lockfile_path)
|
16
|
-
end
|
17
|
-
|
18
|
-
def ephemeral_lockfile
|
19
|
-
Lockfile.new(self, nil)
|
20
|
-
end
|
21
|
-
|
22
14
|
def tmp_path
|
23
15
|
part = config_db["tmp"] || ".tmp"
|
24
16
|
project_path.join(part)
|
@@ -6,4 +6,224 @@ module Librarian
|
|
6
6
|
extend self
|
7
7
|
extend Librarian
|
8
8
|
end
|
9
|
+
|
10
|
+
class Dependency
|
11
|
+
include Librarian::Puppet::Util
|
12
|
+
|
13
|
+
def initialize(name, requirement, source)
|
14
|
+
assert_name_valid! name
|
15
|
+
|
16
|
+
# Issue #235 fail if forge source is not defined
|
17
|
+
raise Error, "forge entry is not defined in Puppetfile" if source.instance_of?(Array) && source.empty?
|
18
|
+
|
19
|
+
# let's settle on provider-module syntax instead of provider/module
|
20
|
+
self.name = normalize_name(name)
|
21
|
+
self.requirement = Requirement.new(requirement)
|
22
|
+
self.source = source
|
23
|
+
|
24
|
+
@manifests = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
class Requirement
|
28
|
+
def initialize(*args)
|
29
|
+
args = initialize_normalize_args(args)
|
30
|
+
self.backing = Gem::Requirement.create(puppet_to_gem_versions(args))
|
31
|
+
end
|
32
|
+
|
33
|
+
def puppet_to_gem_versions(args)
|
34
|
+
args.map do |arg|
|
35
|
+
case arg
|
36
|
+
when Array
|
37
|
+
arg.map { |v| Librarian::Puppet::Requirement.new(v).gem_requirement }
|
38
|
+
when String
|
39
|
+
Librarian::Puppet::Requirement.new(arg).gem_requirement
|
40
|
+
else
|
41
|
+
# Gem::Requirement, convert to string (ie. =1.0) so we can concat later
|
42
|
+
# Gem::Requirements can not be concatenated
|
43
|
+
arg.requirements.map{|x,y| "#{x}#{y}"}
|
44
|
+
end
|
45
|
+
end.flatten
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
alias :eql? :==
|
50
|
+
|
51
|
+
def hash
|
52
|
+
self.to_s.hash
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
# Fixes for librarian not yet released in their gem
|
57
|
+
module Mock
|
58
|
+
module Source
|
59
|
+
class Mock
|
60
|
+
alias :eql? :==
|
61
|
+
|
62
|
+
def hash
|
63
|
+
self.to_s.hash
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
module Source
|
69
|
+
class Git
|
70
|
+
alias :eql? :==
|
71
|
+
|
72
|
+
def hash
|
73
|
+
self.to_s.hash
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Path
|
78
|
+
alias :eql? :==
|
79
|
+
|
80
|
+
def hash
|
81
|
+
self.to_s.hash
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
class ManifestSet
|
87
|
+
include Librarian::Puppet::Util
|
88
|
+
|
89
|
+
private
|
90
|
+
|
91
|
+
# Check if module doesn't exist and fail fast
|
92
|
+
def dependencies_of(names)
|
93
|
+
names = Array === names ? names.dup : names.to_a
|
94
|
+
assert_strings!(names)
|
95
|
+
|
96
|
+
deps = Set.new
|
97
|
+
until names.empty?
|
98
|
+
name = normalize_name(names.shift)
|
99
|
+
next if deps.include?(name)
|
100
|
+
|
101
|
+
deps << name
|
102
|
+
raise(Error, "Unable to find module #{name}. Your Puppetfile may be out of sync with the lock, try running 'librarian-puppet install' first") if index[name].nil?
|
103
|
+
names.concat index[name].dependencies.map(&:name)
|
104
|
+
end
|
105
|
+
deps.to_a
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class Manifest
|
110
|
+
class PreReleaseVersion
|
111
|
+
|
112
|
+
# Compares pre-release component ids using Semver 2.0.0 spec
|
113
|
+
def self.compare_components(this_id,other_id)
|
114
|
+
case # Strings have higher precedence than numbers
|
115
|
+
when (this_id.is_a?(Integer) and other_id.is_a?(String))
|
116
|
+
-1
|
117
|
+
when (this_id.is_a?(String) and other_id.is_a?(Integer))
|
118
|
+
1
|
119
|
+
else
|
120
|
+
this_id <=> other_id
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Parses pre-release components `a.b.c` into an array ``[a,b,c]`
|
125
|
+
# Converts numeric components into +Integer+
|
126
|
+
def self.parse(prerelease)
|
127
|
+
if prerelease.nil?
|
128
|
+
[]
|
129
|
+
else
|
130
|
+
prerelease.split('.').collect do |id|
|
131
|
+
id = Integer(id) if /^[0-9]+$/ =~ id
|
132
|
+
id
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
include Comparable
|
138
|
+
|
139
|
+
attr_reader :components
|
140
|
+
|
141
|
+
def initialize(prerelease)
|
142
|
+
@prerelease = prerelease
|
143
|
+
@components = PreReleaseVersion.parse(prerelease)
|
144
|
+
end
|
145
|
+
|
146
|
+
def to_s
|
147
|
+
@prerelease
|
148
|
+
end
|
149
|
+
|
150
|
+
def <=>(other)
|
151
|
+
# null-fill zip array to prevent loss of components
|
152
|
+
z = Array.new([components.length,other.components.length])
|
153
|
+
|
154
|
+
# Compare each component against the other
|
155
|
+
comp = z.zip(components,other.components).collect do |ids|
|
156
|
+
case # All components being equal, the version with more of them takes precedence
|
157
|
+
when ids[1].nil? # Self has less elements, other wins
|
158
|
+
-1
|
159
|
+
when ids[2].nil? # Other has less elements, self wins
|
160
|
+
1
|
161
|
+
else
|
162
|
+
PreReleaseVersion.compare_components(ids[1],ids[2])
|
163
|
+
end
|
164
|
+
end
|
165
|
+
# Chose the first non-zero comparison or return 0
|
166
|
+
comp.delete_if {|c| c == 0}[0] || 0
|
167
|
+
end
|
168
|
+
end
|
169
|
+
class Version
|
170
|
+
@@SEMANTIC_VERSION_PATTERN = /^([0-9]+\.[0-9]+(?:\.[0-9]+)?)(?:-([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?(?:\+([0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*))?$/
|
171
|
+
def self.parse_semver(version_string)
|
172
|
+
parsed = @@SEMANTIC_VERSION_PATTERN.match(version_string.strip)
|
173
|
+
if parsed
|
174
|
+
{
|
175
|
+
:full_version => parsed[0],
|
176
|
+
:version => parsed[1],
|
177
|
+
:prerelease => (PreReleaseVersion.new(parsed[2]) if parsed[2]),
|
178
|
+
:build => parsed[3]
|
179
|
+
}
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
attr_reader :prerelease
|
184
|
+
|
185
|
+
def initialize(*args)
|
186
|
+
args = initialize_normalize_args(args)
|
187
|
+
semver = Version.parse_semver(*args)
|
188
|
+
if semver
|
189
|
+
self.backing = Gem::Version.new(semver[:version])
|
190
|
+
@prerelease = semver[:prerelease]
|
191
|
+
@full_version = semver[:full_version]
|
192
|
+
else
|
193
|
+
self.backing = Gem::Version.new(*args)
|
194
|
+
@full_version = to_gem_version.to_s
|
195
|
+
end
|
196
|
+
end
|
197
|
+
|
198
|
+
def <=>(other)
|
199
|
+
cmp = to_gem_version <=> other.to_gem_version
|
200
|
+
|
201
|
+
# Should compare pre-release versions?
|
202
|
+
if cmp == 0 and not (prerelease.nil? and other.prerelease.nil?)
|
203
|
+
case # Versions without prerelease take precedence
|
204
|
+
when (prerelease.nil? and not other.prerelease.nil?)
|
205
|
+
1
|
206
|
+
when (not prerelease.nil? and other.prerelease.nil?)
|
207
|
+
-1
|
208
|
+
else
|
209
|
+
prerelease <=> other.prerelease
|
210
|
+
end
|
211
|
+
else
|
212
|
+
cmp
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
def to_s
|
217
|
+
@full_version
|
218
|
+
end
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
class Logger
|
223
|
+
def warn(string = nil, &block)
|
224
|
+
return unless ui
|
225
|
+
|
226
|
+
ui.warn(string || yield)
|
227
|
+
end
|
228
|
+
end
|
9
229
|
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'librarian/manifest'
|
2
|
+
require 'librarian/dependency'
|
3
|
+
require 'librarian/manifest_set'
|
4
|
+
|
5
|
+
module Librarian
|
6
|
+
class Lockfile
|
7
|
+
class Parser
|
8
|
+
include Librarian::Puppet::Util
|
9
|
+
|
10
|
+
def parse(string)
|
11
|
+
string = string.dup
|
12
|
+
source_type_names_map = Hash[dsl_class.source_types.map{|t| [t[1].lock_name, t[1]]}]
|
13
|
+
source_type_names = dsl_class.source_types.map{|t| t[1].lock_name}
|
14
|
+
lines = string.split(/(\r|\n|\r\n)+/).select{|l| l =~ /\S/}
|
15
|
+
sources = []
|
16
|
+
while source_type_names.include?(lines.first)
|
17
|
+
source = {}
|
18
|
+
source_type_name = lines.shift
|
19
|
+
source[:type] = source_type_names_map[source_type_name]
|
20
|
+
options = {}
|
21
|
+
while lines.first =~ /^ {2}([\w\-\/]+):\s+(.+)$/
|
22
|
+
lines.shift
|
23
|
+
options[$1.to_sym] = $2
|
24
|
+
end
|
25
|
+
source[:options] = options
|
26
|
+
lines.shift # specs
|
27
|
+
manifests = {}
|
28
|
+
while lines.first =~ /^ {4}([\w\-\/]+) \((.*)\)$/ # This change allows forward slash
|
29
|
+
lines.shift
|
30
|
+
name, version = normalize_name($1), $2
|
31
|
+
manifests[name] = {:version => version, :dependencies => {}}
|
32
|
+
while lines.first =~ /^ {6}([\w\-\/]+) \((.*)\)$/
|
33
|
+
lines.shift
|
34
|
+
manifests[name][:dependencies][$1] = $2.split(/,\s*/)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
source[:manifests] = manifests
|
38
|
+
sources << source
|
39
|
+
end
|
40
|
+
manifests = compile(sources)
|
41
|
+
manifests_index = Hash[manifests.map{|m| [m.name, m]}]
|
42
|
+
raise StandardError, "Expected DEPENDENCIES topic!" unless lines.shift == "DEPENDENCIES"
|
43
|
+
dependencies = []
|
44
|
+
while lines.first =~ /^ {2}([\w\-\/]+)(?: \((.*)\))?$/ # This change allows forward slash
|
45
|
+
lines.shift
|
46
|
+
name, requirement = normalize_name($1), $2.split(/,\s*/)
|
47
|
+
dependencies << Dependency.new(name, requirement, manifests_index[name].source)
|
48
|
+
end
|
49
|
+
|
50
|
+
Resolution.new(dependencies, manifests)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Librarian
|
2
|
+
module Puppet
|
3
|
+
class Requirement
|
4
|
+
attr_reader :requirement
|
5
|
+
|
6
|
+
def initialize(requirement)
|
7
|
+
@requirement = requirement || ">=0"
|
8
|
+
end
|
9
|
+
|
10
|
+
def gem_requirement
|
11
|
+
if range_requirement?
|
12
|
+
[@range_match[1], @range_match[2]]
|
13
|
+
elsif pessimistic_requirement?
|
14
|
+
"~> #{@pessimistic_match[1]}.0"
|
15
|
+
else
|
16
|
+
requirement
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_s
|
21
|
+
gem_requirement.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def range_requirement?
|
27
|
+
@range_match ||= requirement.match(/(>=? ?\d+(?:\.\d+){0,2}) (<=? ?\d+(?:\.\d+){0,2})/)
|
28
|
+
end
|
29
|
+
|
30
|
+
def pessimistic_requirement?
|
31
|
+
@pessimistic_match ||= requirement.match(/(\d+(?:\.\d+)?)\.x/)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
require 'uri'
|
2
2
|
require 'librarian/puppet/util'
|
3
3
|
require 'librarian/puppet/source/forge/repo_v1'
|
4
|
-
|
4
|
+
require 'librarian/puppet/source/forge/repo_v3'
|
5
5
|
|
6
6
|
module Librarian
|
7
7
|
module Puppet
|
@@ -12,14 +12,6 @@ module Librarian
|
|
12
12
|
class << self
|
13
13
|
LOCK_NAME = 'FORGE'
|
14
14
|
|
15
|
-
def default=(source)
|
16
|
-
@@default = source
|
17
|
-
end
|
18
|
-
|
19
|
-
def default
|
20
|
-
@@default
|
21
|
-
end
|
22
|
-
|
23
15
|
def lock_name
|
24
16
|
LOCK_NAME
|
25
17
|
end
|
@@ -61,10 +53,10 @@ module Librarian
|
|
61
53
|
def initialize(environment, uri, options = {})
|
62
54
|
self.environment = environment
|
63
55
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
56
|
+
if uri =~ %r{^http(s)?://forge\.puppetlabs\.com}
|
57
|
+
uri = "https://forgeapi.puppetlabs.com"
|
58
|
+
warn { "Replacing Puppet Forge API URL to use v3 #{uri}. You should update your Puppetfile" }
|
59
|
+
end
|
68
60
|
|
69
61
|
@uri = URI::parse(uri)
|
70
62
|
@cache_path = nil
|
@@ -143,7 +135,7 @@ module Librarian
|
|
143
135
|
|
144
136
|
def fetch_dependencies(name, version, version_uri)
|
145
137
|
repo(name).dependencies(version).map do |k, v|
|
146
|
-
v =
|
138
|
+
v = Requirement.new(v).gem_requirement
|
147
139
|
Dependency.new(k, v, nil)
|
148
140
|
end
|
149
141
|
end
|
@@ -159,11 +151,11 @@ module Librarian
|
|
159
151
|
|
160
152
|
unless @repo[name]
|
161
153
|
# if we are using the official Forge then use API v3, otherwise stick to v1 for now
|
162
|
-
|
163
|
-
|
164
|
-
|
154
|
+
if uri.hostname =~ /\.puppetlabs\.com$/ || !environment.use_v1_api
|
155
|
+
@repo[name] = RepoV3.new(self, name)
|
156
|
+
else
|
165
157
|
@repo[name] = RepoV1.new(self, name)
|
166
|
-
|
158
|
+
end
|
167
159
|
end
|
168
160
|
@repo[name]
|
169
161
|
end
|
@@ -33,9 +33,30 @@ module Librarian
|
|
33
33
|
|
34
34
|
private
|
35
35
|
|
36
|
-
#
|
37
|
-
|
36
|
+
# Issue #223 dependencies may be duplicated
|
37
|
+
# and convert organization/modulename to organization-modulename
|
38
|
+
def clear_duplicated_dependencies(data)
|
38
39
|
return nil if data.nil?
|
40
|
+
data.each do |m,versions|
|
41
|
+
versions.each do |v|
|
42
|
+
if v["dependencies"] and !v["dependencies"].empty?
|
43
|
+
# convert organization/modulename to organization-modulename
|
44
|
+
v["dependencies"].each {|d| d[0] = normalize_name(d[0])}
|
45
|
+
|
46
|
+
dependency_names = v["dependencies"].map {|d| d[0]}
|
47
|
+
duplicated = dependency_names.select{ |e| dependency_names.count(e) > 1 }
|
48
|
+
unless duplicated.empty?
|
49
|
+
duplicated.uniq.each do |module_duplicated|
|
50
|
+
to_remove = []
|
51
|
+
v["dependencies"].each_index{|i| to_remove << i if module_duplicated == v["dependencies"][i][0]}
|
52
|
+
warn { "Module #{m}@#{v["version"]} contains duplicated dependencies for #{module_duplicated}, ignoring all but the first of #{to_remove.map {|i| v["dependencies"][i]}}" }
|
53
|
+
to_remove.slice(1..-1).reverse.each {|i| v["dependencies"].delete_at(i) }
|
54
|
+
v["dependencies"] = v["dependencies"] - to_remove.slice(1..-1)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
39
60
|
# convert organization/modulename to organization-modulename
|
40
61
|
data.keys.each do |m|
|
41
62
|
if m =~ %r{.*/.*}
|
@@ -50,7 +71,7 @@ module Librarian
|
|
50
71
|
def api_data(module_name)
|
51
72
|
return @api_data[module_name] if @api_data
|
52
73
|
# call API and cache data
|
53
|
-
@api_data =
|
74
|
+
@api_data = clear_duplicated_dependencies(api_call(module_name))
|
54
75
|
if @api_data.nil?
|
55
76
|
raise Error, "Unable to find module '#{name}' on #{source}"
|
56
77
|
end
|
@@ -62,7 +83,7 @@ module Librarian
|
|
62
83
|
# if we already got all the versions, find in cached data
|
63
84
|
return @api_data[module_name].detect{|x| x['version'] == version.to_s} if @api_data
|
64
85
|
# otherwise call the api for this version if not cached already
|
65
|
-
@api_version_data[version] =
|
86
|
+
@api_version_data[version] = clear_duplicated_dependencies(api_call(name, version)) if @api_version_data[version].nil?
|
66
87
|
@api_version_data[version]
|
67
88
|
end
|
68
89
|
|
@@ -43,16 +43,19 @@ module Librarian
|
|
43
43
|
end
|
44
44
|
|
45
45
|
parsed_metadata['dependencies'].each do |d|
|
46
|
-
gem_requirement =
|
46
|
+
gem_requirement = Requirement.new(d['version_requirement']).gem_requirement
|
47
47
|
new_dependency = Dependency.new(d['name'], gem_requirement, forge_source)
|
48
|
-
dependencies
|
48
|
+
# Avoid duplicated dependencies with different sources
|
49
|
+
unless dependencies.find { |spec_dependency| spec_dependency.name == new_dependency.name && spec_dependency.requirement == new_dependency.requirement }
|
50
|
+
dependencies << new_dependency
|
51
|
+
end
|
49
52
|
end
|
50
53
|
|
51
54
|
dependencies
|
52
55
|
end
|
53
56
|
|
54
57
|
def forge_source
|
55
|
-
Forge.
|
58
|
+
Forge.from_lock_options(environment, :remote => "https://forgeapi.puppetlabs.com")
|
56
59
|
end
|
57
60
|
|
58
61
|
private
|
@@ -102,11 +105,7 @@ module Librarian
|
|
102
105
|
def parsed_metadata
|
103
106
|
if @metadata.nil?
|
104
107
|
@metadata = if metadata?
|
105
|
-
|
106
|
-
JSON.parse(File.read(metadata))
|
107
|
-
rescue JSON::ParserError => e
|
108
|
-
raise Error, "Unable to parse json file #{metadata}: #{e}"
|
109
|
-
end
|
108
|
+
JSON.parse(File.read(metadata))
|
110
109
|
elsif modulefile?
|
111
110
|
# translate Modulefile to metadata.json
|
112
111
|
evaluated = evaluate_modulefile(modulefile)
|
@@ -160,8 +159,8 @@ module Librarian
|
|
160
159
|
return true if path.join('manifests').exist?
|
161
160
|
return true if path.join('lib').join('puppet').exist?
|
162
161
|
return true if path.join('lib').join('facter').exist?
|
163
|
-
debug { "Could not find manifests, lib/puppet or lib/facter under #{path},
|
164
|
-
|
162
|
+
debug { "Could not find manifests, lib/puppet or lib/facter under #{path}, assuming is not a puppet module" }
|
163
|
+
false
|
165
164
|
end
|
166
165
|
end
|
167
166
|
end
|
@@ -30,7 +30,7 @@ module Librarian
|
|
30
30
|
else
|
31
31
|
begin
|
32
32
|
FileUtils.cp_r(src, dest, :preserve => true)
|
33
|
-
rescue Errno::ENOENT
|
33
|
+
rescue Errno::ENOENT
|
34
34
|
debug { "Failed to copy from #{src} to #{dest} preserving file types, trying again without preserving them" }
|
35
35
|
FileUtils.rm_rf(dest)
|
36
36
|
FileUtils.cp_r(src, dest)
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: librarian-puppet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tim Sharpe
|
@@ -9,160 +9,160 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date:
|
12
|
+
date: 2014-10-14 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
15
|
+
name: librarian
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- -
|
18
|
+
- - '>='
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 0.
|
20
|
+
version: 0.1.2
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - '>='
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 0.
|
27
|
+
version: 0.1.2
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: rsync
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- -
|
32
|
+
- - '>='
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '0'
|
35
35
|
type: :runtime
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- -
|
39
|
+
- - '>='
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
|
-
name:
|
43
|
+
name: puppet_forge
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- -
|
46
|
+
- - '>='
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '0'
|
49
49
|
type: :runtime
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- -
|
53
|
+
- - '>='
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rake
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- -
|
60
|
+
- - '>='
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '0'
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- -
|
67
|
+
- - '>='
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: rspec
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- -
|
74
|
+
- - '>='
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- -
|
81
|
+
- - '>='
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: cucumber
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- -
|
88
|
+
- - '>='
|
89
89
|
- !ruby/object:Gem::Version
|
90
90
|
version: '0'
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
|
-
- -
|
95
|
+
- - '>='
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
98
|
- !ruby/object:Gem::Dependency
|
99
99
|
name: aruba
|
100
100
|
requirement: !ruby/object:Gem::Requirement
|
101
101
|
requirements:
|
102
|
-
- -
|
102
|
+
- - '>='
|
103
103
|
- !ruby/object:Gem::Version
|
104
104
|
version: '0'
|
105
105
|
type: :development
|
106
106
|
prerelease: false
|
107
107
|
version_requirements: !ruby/object:Gem::Requirement
|
108
108
|
requirements:
|
109
|
-
- -
|
109
|
+
- - '>='
|
110
110
|
- !ruby/object:Gem::Version
|
111
111
|
version: '0'
|
112
112
|
- !ruby/object:Gem::Dependency
|
113
113
|
name: puppet
|
114
114
|
requirement: !ruby/object:Gem::Requirement
|
115
115
|
requirements:
|
116
|
-
- -
|
116
|
+
- - '>='
|
117
117
|
- !ruby/object:Gem::Version
|
118
118
|
version: '0'
|
119
119
|
type: :development
|
120
120
|
prerelease: false
|
121
121
|
version_requirements: !ruby/object:Gem::Requirement
|
122
122
|
requirements:
|
123
|
-
- -
|
123
|
+
- - '>='
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: '0'
|
126
126
|
- !ruby/object:Gem::Dependency
|
127
127
|
name: minitest
|
128
128
|
requirement: !ruby/object:Gem::Requirement
|
129
129
|
requirements:
|
130
|
-
- -
|
130
|
+
- - ~>
|
131
131
|
- !ruby/object:Gem::Version
|
132
132
|
version: '5'
|
133
133
|
type: :development
|
134
134
|
prerelease: false
|
135
135
|
version_requirements: !ruby/object:Gem::Requirement
|
136
136
|
requirements:
|
137
|
-
- -
|
137
|
+
- - ~>
|
138
138
|
- !ruby/object:Gem::Version
|
139
139
|
version: '5'
|
140
140
|
- !ruby/object:Gem::Dependency
|
141
141
|
name: mocha
|
142
142
|
requirement: !ruby/object:Gem::Requirement
|
143
143
|
requirements:
|
144
|
-
- -
|
144
|
+
- - '>='
|
145
145
|
- !ruby/object:Gem::Version
|
146
146
|
version: '0'
|
147
147
|
type: :development
|
148
148
|
prerelease: false
|
149
149
|
version_requirements: !ruby/object:Gem::Requirement
|
150
150
|
requirements:
|
151
|
-
- -
|
151
|
+
- - '>='
|
152
152
|
- !ruby/object:Gem::Version
|
153
153
|
version: '0'
|
154
154
|
- !ruby/object:Gem::Dependency
|
155
155
|
name: simplecov
|
156
156
|
requirement: !ruby/object:Gem::Requirement
|
157
157
|
requirements:
|
158
|
-
- -
|
158
|
+
- - '>='
|
159
159
|
- !ruby/object:Gem::Version
|
160
160
|
version: 0.9.0
|
161
161
|
type: :development
|
162
162
|
prerelease: false
|
163
163
|
version_requirements: !ruby/object:Gem::Requirement
|
164
164
|
requirements:
|
165
|
-
- -
|
165
|
+
- - '>='
|
166
166
|
- !ruby/object:Gem::Version
|
167
167
|
version: 0.9.0
|
168
168
|
description: |-
|
@@ -177,20 +177,19 @@ executables:
|
|
177
177
|
extensions: []
|
178
178
|
extra_rdoc_files: []
|
179
179
|
files:
|
180
|
-
-
|
180
|
+
- .gitignore
|
181
181
|
- LICENSE
|
182
182
|
- README.md
|
183
183
|
- bin/librarian-puppet
|
184
184
|
- lib/librarian/puppet.rb
|
185
185
|
- lib/librarian/puppet/action.rb
|
186
186
|
- lib/librarian/puppet/action/install.rb
|
187
|
-
- lib/librarian/puppet/action/resolve.rb
|
188
187
|
- lib/librarian/puppet/cli.rb
|
189
|
-
- lib/librarian/puppet/dependency.rb
|
190
188
|
- lib/librarian/puppet/dsl.rb
|
191
189
|
- lib/librarian/puppet/environment.rb
|
192
190
|
- lib/librarian/puppet/extension.rb
|
193
|
-
- lib/librarian/puppet/lockfile.rb
|
191
|
+
- lib/librarian/puppet/lockfile/parser.rb
|
192
|
+
- lib/librarian/puppet/requirement.rb
|
194
193
|
- lib/librarian/puppet/source.rb
|
195
194
|
- lib/librarian/puppet/source/forge.rb
|
196
195
|
- lib/librarian/puppet/source/forge/repo.rb
|
@@ -215,17 +214,17 @@ require_paths:
|
|
215
214
|
- lib
|
216
215
|
required_ruby_version: !ruby/object:Gem::Requirement
|
217
216
|
requirements:
|
218
|
-
- -
|
217
|
+
- - '>='
|
219
218
|
- !ruby/object:Gem::Version
|
220
|
-
version:
|
219
|
+
version: 1.9.0
|
221
220
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
222
221
|
requirements:
|
223
|
-
- -
|
222
|
+
- - '>='
|
224
223
|
- !ruby/object:Gem::Version
|
225
224
|
version: '0'
|
226
225
|
requirements: []
|
227
226
|
rubyforge_project:
|
228
|
-
rubygems_version: 2.
|
227
|
+
rubygems_version: 2.2.2
|
229
228
|
signing_key:
|
230
229
|
specification_version: 4
|
231
230
|
summary: Bundler for your Puppet modules
|
@@ -1,19 +0,0 @@
|
|
1
|
-
module Librarian
|
2
|
-
module Puppet
|
3
|
-
module Action
|
4
|
-
class Resolve < Librarian::Action::Resolve
|
5
|
-
include Librarian::Puppet::Util
|
6
|
-
|
7
|
-
def run
|
8
|
-
super
|
9
|
-
manifests = environment.lock.manifests.select{ |m| m.name }
|
10
|
-
dupes = manifests.group_by{ |m| module_name(m.name) }.select { |k, v| v.size > 1 }
|
11
|
-
dupes.each do |k,v|
|
12
|
-
warn("Dependency on module '#{k}' is fullfilled by multiple modules and only one will be used: #{v.map{|m|m.name}}")
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Librarian
|
2
|
-
module Puppet
|
3
|
-
|
4
|
-
class Dependency < Librarian::Dependency
|
5
|
-
|
6
|
-
include Librarian::Puppet::Util
|
7
|
-
|
8
|
-
def initialize(name, requirement, source)
|
9
|
-
# Issue #235 fail if forge source is not defined
|
10
|
-
raise Error, "forge entry is not defined in Puppetfile" if source.instance_of?(Array) && source.empty?
|
11
|
-
|
12
|
-
super(normalize_name(name), requirement, source)
|
13
|
-
end
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
end
|
18
|
-
end
|
@@ -1,39 +0,0 @@
|
|
1
|
-
# Extend Lockfile to normalize module names from acme/mod to acme-mod
|
2
|
-
module Librarian
|
3
|
-
module Puppet
|
4
|
-
class Lockfile < Librarian::Lockfile
|
5
|
-
|
6
|
-
# Extend the parser to normalize module names in old .lock files, converting / to -
|
7
|
-
class Parser < Librarian::Lockfile::Parser
|
8
|
-
|
9
|
-
include Librarian::Puppet::Util
|
10
|
-
|
11
|
-
def extract_and_parse_sources(lines)
|
12
|
-
sources = super
|
13
|
-
sources.each do |source|
|
14
|
-
source[:manifests] = Hash[source[:manifests].map do |name,manifest|
|
15
|
-
[normalize_name(name), manifest]
|
16
|
-
end]
|
17
|
-
end
|
18
|
-
sources
|
19
|
-
end
|
20
|
-
|
21
|
-
def extract_and_parse_dependencies(lines, manifests_index)
|
22
|
-
# when looking up in manifests_index normalize the name beforehand
|
23
|
-
class << manifests_index
|
24
|
-
include Librarian::Puppet::Util
|
25
|
-
alias_method :old_lookup, :[]
|
26
|
-
define_method(:[]) { |k| self.old_lookup(normalize_name(k)) }
|
27
|
-
end
|
28
|
-
super(lines, manifests_index)
|
29
|
-
end
|
30
|
-
|
31
|
-
end
|
32
|
-
|
33
|
-
def load(string)
|
34
|
-
Parser.new(environment).parse(string)
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|