librarian-puppet-maestrodev 0.9.7
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.
- data/.gitignore +3 -0
- data/LICENSE +20 -0
- data/README.md +187 -0
- data/bin/librarian-puppet +9 -0
- data/lib/librarian/puppet.rb +13 -0
- data/lib/librarian/puppet/cli.rb +85 -0
- data/lib/librarian/puppet/dsl.rb +16 -0
- data/lib/librarian/puppet/environment.rb +54 -0
- data/lib/librarian/puppet/extension.rb +41 -0
- data/lib/librarian/puppet/lockfile/parser.rb +53 -0
- data/lib/librarian/puppet/source.rb +4 -0
- data/lib/librarian/puppet/source/forge.rb +279 -0
- data/lib/librarian/puppet/source/git.rb +114 -0
- data/lib/librarian/puppet/source/githubtarball.rb +234 -0
- data/lib/librarian/puppet/source/local.rb +57 -0
- data/lib/librarian/puppet/source/path.rb +12 -0
- data/lib/librarian/puppet/templates/Puppetfile +10 -0
- data/lib/librarian/puppet/version.rb +5 -0
- data/vendor/librarian/CHANGELOG.md +185 -0
- data/vendor/librarian/Gemfile +6 -0
- data/vendor/librarian/MIT-LICENSE +20 -0
- data/vendor/librarian/README.md +403 -0
- data/vendor/librarian/Rakefile +34 -0
- data/vendor/librarian/bin/librarian-chef +7 -0
- data/vendor/librarian/bin/librarian-mock +7 -0
- data/vendor/librarian/config/cucumber.yaml +1 -0
- data/vendor/librarian/features/chef/cli/init.feature +11 -0
- data/vendor/librarian/features/chef/cli/install.feature +64 -0
- data/vendor/librarian/features/chef/cli/show.feature +77 -0
- data/vendor/librarian/features/chef/cli/version.feature +11 -0
- data/vendor/librarian/features/support/env.rb +9 -0
- data/vendor/librarian/lib/librarian.rb +19 -0
- data/vendor/librarian/lib/librarian/action.rb +5 -0
- data/vendor/librarian/lib/librarian/action/base.rb +24 -0
- data/vendor/librarian/lib/librarian/action/clean.rb +44 -0
- data/vendor/librarian/lib/librarian/action/ensure.rb +24 -0
- data/vendor/librarian/lib/librarian/action/install.rb +99 -0
- data/vendor/librarian/lib/librarian/action/resolve.rb +81 -0
- data/vendor/librarian/lib/librarian/action/update.rb +78 -0
- data/vendor/librarian/lib/librarian/chef.rb +1 -0
- data/vendor/librarian/lib/librarian/chef/cli.rb +48 -0
- data/vendor/librarian/lib/librarian/chef/dsl.rb +15 -0
- data/vendor/librarian/lib/librarian/chef/environment.rb +27 -0
- data/vendor/librarian/lib/librarian/chef/extension.rb +9 -0
- data/vendor/librarian/lib/librarian/chef/integration/knife.rb +42 -0
- data/vendor/librarian/lib/librarian/chef/manifest_reader.rb +59 -0
- data/vendor/librarian/lib/librarian/chef/source.rb +3 -0
- data/vendor/librarian/lib/librarian/chef/source/git.rb +25 -0
- data/vendor/librarian/lib/librarian/chef/source/local.rb +69 -0
- data/vendor/librarian/lib/librarian/chef/source/path.rb +12 -0
- data/vendor/librarian/lib/librarian/chef/source/site.rb +446 -0
- data/vendor/librarian/lib/librarian/chef/templates/Cheffile +15 -0
- data/vendor/librarian/lib/librarian/cli.rb +205 -0
- data/vendor/librarian/lib/librarian/cli/manifest_presenter.rb +79 -0
- data/vendor/librarian/lib/librarian/config.rb +7 -0
- data/vendor/librarian/lib/librarian/config/database.rb +205 -0
- data/vendor/librarian/lib/librarian/config/file_source.rb +47 -0
- data/vendor/librarian/lib/librarian/config/hash_source.rb +33 -0
- data/vendor/librarian/lib/librarian/config/source.rb +149 -0
- data/vendor/librarian/lib/librarian/dependency.rb +91 -0
- data/vendor/librarian/lib/librarian/dsl.rb +108 -0
- data/vendor/librarian/lib/librarian/dsl/receiver.rb +48 -0
- data/vendor/librarian/lib/librarian/dsl/target.rb +172 -0
- data/vendor/librarian/lib/librarian/environment.rb +134 -0
- data/vendor/librarian/lib/librarian/error.rb +4 -0
- data/vendor/librarian/lib/librarian/helpers.rb +13 -0
- data/vendor/librarian/lib/librarian/lockfile.rb +29 -0
- data/vendor/librarian/lib/librarian/lockfile/compiler.rb +66 -0
- data/vendor/librarian/lib/librarian/lockfile/parser.rb +100 -0
- data/vendor/librarian/lib/librarian/logger.rb +46 -0
- data/vendor/librarian/lib/librarian/manifest.rb +132 -0
- data/vendor/librarian/lib/librarian/manifest_set.rb +153 -0
- data/vendor/librarian/lib/librarian/mock.rb +1 -0
- data/vendor/librarian/lib/librarian/mock/cli.rb +19 -0
- data/vendor/librarian/lib/librarian/mock/dsl.rb +15 -0
- data/vendor/librarian/lib/librarian/mock/environment.rb +24 -0
- data/vendor/librarian/lib/librarian/mock/extension.rb +9 -0
- data/vendor/librarian/lib/librarian/mock/source.rb +1 -0
- data/vendor/librarian/lib/librarian/mock/source/mock.rb +97 -0
- data/vendor/librarian/lib/librarian/mock/source/mock/registry.rb +83 -0
- data/vendor/librarian/lib/librarian/resolution.rb +44 -0
- data/vendor/librarian/lib/librarian/resolver.rb +78 -0
- data/vendor/librarian/lib/librarian/resolver/implementation.rb +118 -0
- data/vendor/librarian/lib/librarian/source.rb +2 -0
- data/vendor/librarian/lib/librarian/source/git.rb +150 -0
- data/vendor/librarian/lib/librarian/source/git/repository.rb +217 -0
- data/vendor/librarian/lib/librarian/source/local.rb +61 -0
- data/vendor/librarian/lib/librarian/source/path.rb +74 -0
- data/vendor/librarian/lib/librarian/spec.rb +13 -0
- data/vendor/librarian/lib/librarian/spec_change_set.rb +173 -0
- data/vendor/librarian/lib/librarian/specfile.rb +18 -0
- data/vendor/librarian/lib/librarian/support/abstract_method.rb +21 -0
- data/vendor/librarian/lib/librarian/ui.rb +64 -0
- data/vendor/librarian/lib/librarian/version.rb +3 -0
- data/vendor/librarian/librarian.gemspec +34 -0
- data/vendor/librarian/spec/functional/chef/source/git_spec.rb +432 -0
- data/vendor/librarian/spec/functional/chef/source/site_spec.rb +215 -0
- data/vendor/librarian/spec/functional/source/git/repository_spec.rb +149 -0
- data/vendor/librarian/spec/unit/action/base_spec.rb +18 -0
- data/vendor/librarian/spec/unit/action/clean_spec.rb +102 -0
- data/vendor/librarian/spec/unit/action/ensure_spec.rb +37 -0
- data/vendor/librarian/spec/unit/action/install_spec.rb +111 -0
- data/vendor/librarian/spec/unit/config/database_spec.rb +319 -0
- data/vendor/librarian/spec/unit/dependency_spec.rb +36 -0
- data/vendor/librarian/spec/unit/dsl_spec.rb +194 -0
- data/vendor/librarian/spec/unit/environment_spec.rb +9 -0
- data/vendor/librarian/spec/unit/lockfile/parser_spec.rb +162 -0
- data/vendor/librarian/spec/unit/lockfile_spec.rb +65 -0
- data/vendor/librarian/spec/unit/manifest_set_spec.rb +202 -0
- data/vendor/librarian/spec/unit/manifest_spec.rb +36 -0
- data/vendor/librarian/spec/unit/mock/source/mock_spec.rb +22 -0
- data/vendor/librarian/spec/unit/resolver_spec.rb +192 -0
- data/vendor/librarian/spec/unit/source/git_spec.rb +29 -0
- data/vendor/librarian/spec/unit/spec_change_set_spec.rb +169 -0
- metadata +227 -0
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'net/http'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Librarian
|
|
6
|
+
module Puppet
|
|
7
|
+
module Source
|
|
8
|
+
class Forge
|
|
9
|
+
class Repo
|
|
10
|
+
|
|
11
|
+
attr_accessor :source, :name
|
|
12
|
+
private :source=, :name=
|
|
13
|
+
|
|
14
|
+
def initialize(source, name)
|
|
15
|
+
self.source = source
|
|
16
|
+
self.name = name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def versions
|
|
20
|
+
data = api_call("#{name}.json")
|
|
21
|
+
if data.nil?
|
|
22
|
+
raise Error, "Unable to find module '#{name}' on #{source}"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
data['releases'].map { |r| r['version'] }.sort.reverse
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def dependencies(version)
|
|
29
|
+
data = api_call("api/v1/releases.json?module=#{name}&version=#{version}")
|
|
30
|
+
data[name].first['dependencies']
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def manifests
|
|
34
|
+
versions.map do |version|
|
|
35
|
+
Manifest.new(source, name, version)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def install_version!(version, install_path)
|
|
40
|
+
if environment.local? && !vendored?(name, version)
|
|
41
|
+
raise Error, "Could not find a local copy of #{name} at #{version}."
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
if environment.vendor?
|
|
45
|
+
vendor_cache(name, version) unless vendored?(name, version)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
cache_version_unpacked! version
|
|
49
|
+
|
|
50
|
+
if install_path.exist?
|
|
51
|
+
install_path.rmtree
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
unpacked_path = version_unpacked_cache_path(version).join(name.split('/').last)
|
|
55
|
+
|
|
56
|
+
unless unpacked_path.exist?
|
|
57
|
+
raise Error, "#{unpacked_path} does not exist, something went wrong. Try removing it manually"
|
|
58
|
+
else
|
|
59
|
+
FileUtils.cp_r(unpacked_path, install_path)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def environment
|
|
65
|
+
source.environment
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def cache_path
|
|
69
|
+
@cache_path ||= source.cache_path.join(name)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
def version_unpacked_cache_path(version)
|
|
73
|
+
cache_path.join('version').join(hexdigest(version.to_s))
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def hexdigest(value)
|
|
77
|
+
Digest::MD5.hexdigest(value)
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def cache_version_unpacked!(version)
|
|
81
|
+
path = version_unpacked_cache_path(version)
|
|
82
|
+
return if path.directory?
|
|
83
|
+
|
|
84
|
+
# The puppet module command is only available from puppet versions >= 2.7.13
|
|
85
|
+
#
|
|
86
|
+
# Specifying the version in the gemspec would force people to upgrade puppet while it's still usable for git
|
|
87
|
+
# So we do some more clever checking
|
|
88
|
+
#
|
|
89
|
+
# Executing older versions or via puppet-module tool gives an exit status = 0 .
|
|
90
|
+
#
|
|
91
|
+
check_puppet_module_options
|
|
92
|
+
|
|
93
|
+
path.mkpath
|
|
94
|
+
|
|
95
|
+
target = vendored?(name, version) ? vendored_path(name, version) : name
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
command = "puppet module install --version #{version} --target-dir '#{path}' --modulepath '#{path}' --ignore-dependencies '#{target}'"
|
|
99
|
+
output = `#{command}`
|
|
100
|
+
|
|
101
|
+
# Check for bad exit code
|
|
102
|
+
unless $? == 0
|
|
103
|
+
# Rollback the directory if the puppet module had an error
|
|
104
|
+
path.unlink
|
|
105
|
+
raise Error, "Error executing puppet module install:\n#{command}\nError:\n#{output}"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def check_puppet_module_options
|
|
111
|
+
min_version = Gem::Version.create('2.7.13')
|
|
112
|
+
puppet_version = Gem::Version.create(`puppet --version`.strip)
|
|
113
|
+
|
|
114
|
+
if puppet_version < min_version
|
|
115
|
+
raise Error, "To get modules from the forge, we use the puppet faces module command. For this you need at least puppet version 2.7.13 and you have #{puppet_version}"
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def vendored?(name, version)
|
|
120
|
+
vendored_path(name, version).exist?
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def vendored_path(name, version)
|
|
124
|
+
environment.vendor_cache.join("#{name.sub("/", "-")}-#{version}.tar.gz")
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def vendor_cache(name, version)
|
|
128
|
+
File.open(vendored_path(name, version).to_s, 'w') do |f|
|
|
129
|
+
download(name, version) do |data|
|
|
130
|
+
f << data
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def download(name, version, &block)
|
|
136
|
+
data = api_call("api/v1/releases.json?module=#{name}&version=#{version}")
|
|
137
|
+
|
|
138
|
+
info = data[name].detect {|h| h['version'] == version.to_s }
|
|
139
|
+
|
|
140
|
+
stream(info['file'], &block)
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
def stream(file, &block)
|
|
144
|
+
Net::HTTP.get_response(URI.parse("#{source}#{file}")) do |res|
|
|
145
|
+
res.code
|
|
146
|
+
|
|
147
|
+
res.read_body(&block)
|
|
148
|
+
end
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
private
|
|
152
|
+
|
|
153
|
+
def api_call(path)
|
|
154
|
+
base_url = source.to_s
|
|
155
|
+
resp = Net::HTTP.get_response(URI.parse("#{base_url}/#{path}"))
|
|
156
|
+
if resp.code.to_i != 200
|
|
157
|
+
nil
|
|
158
|
+
else
|
|
159
|
+
data = resp.body
|
|
160
|
+
JSON.parse(data)
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
class << self
|
|
166
|
+
LOCK_NAME = 'FORGE'
|
|
167
|
+
|
|
168
|
+
def lock_name
|
|
169
|
+
LOCK_NAME
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def from_lock_options(environment, options)
|
|
173
|
+
new(environment, options[:remote], options.reject { |k, v| k == :remote })
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def from_spec_args(environment, uri, options)
|
|
177
|
+
recognised_options = []
|
|
178
|
+
unrecognised_options = options.keys - recognised_options
|
|
179
|
+
unless unrecognised_options.empty?
|
|
180
|
+
raise Error, "unrecognised options: #{unrecognised_options.join(", ")}"
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
new(environment, uri, options)
|
|
184
|
+
end
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
attr_accessor :environment
|
|
188
|
+
private :environment=
|
|
189
|
+
attr_reader :uri
|
|
190
|
+
|
|
191
|
+
def initialize(environment, uri, options = {})
|
|
192
|
+
self.environment = environment
|
|
193
|
+
@uri = uri
|
|
194
|
+
@cache_path = nil
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def to_s
|
|
198
|
+
uri
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def ==(other)
|
|
202
|
+
other &&
|
|
203
|
+
self.class == other.class &&
|
|
204
|
+
self.uri == other.uri
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def to_spec_args
|
|
208
|
+
[uri, {}]
|
|
209
|
+
end
|
|
210
|
+
|
|
211
|
+
def to_lock_options
|
|
212
|
+
{:remote => uri}
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def pinned?
|
|
216
|
+
false
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
def unpin!
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def install!(manifest)
|
|
223
|
+
manifest.source == self or raise ArgumentError
|
|
224
|
+
|
|
225
|
+
name = manifest.name
|
|
226
|
+
version = manifest.version
|
|
227
|
+
install_path = install_path(name)
|
|
228
|
+
repo = repo(name)
|
|
229
|
+
|
|
230
|
+
repo.install_version! version, install_path
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def manifest(name, version, dependencies)
|
|
234
|
+
manifest = Manifest.new(self, name)
|
|
235
|
+
manifest.version = version
|
|
236
|
+
manifest.dependencies = dependencies
|
|
237
|
+
manifest
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def cache_path
|
|
241
|
+
@cache_path ||= begin
|
|
242
|
+
dir = Digest::MD5.hexdigest(uri)
|
|
243
|
+
environment.cache_path.join("source/puppet/forge/#{dir}")
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def install_path(name)
|
|
248
|
+
environment.install_path.join(name.split('/').last)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
def fetch_version(name, version_uri)
|
|
252
|
+
versions = repo(name).versions
|
|
253
|
+
if versions.include? version_uri
|
|
254
|
+
version_uri
|
|
255
|
+
else
|
|
256
|
+
versions.first
|
|
257
|
+
end
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def fetch_dependencies(name, version, version_uri)
|
|
261
|
+
repo(name).dependencies(version).map do |k, v|
|
|
262
|
+
Dependency.new(k, v, nil)
|
|
263
|
+
end
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def manifests(name)
|
|
267
|
+
repo(name).manifests
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
private
|
|
271
|
+
|
|
272
|
+
def repo(name)
|
|
273
|
+
@repo ||= {}
|
|
274
|
+
@repo[name] ||= Repo.new(self, name)
|
|
275
|
+
end
|
|
276
|
+
end
|
|
277
|
+
end
|
|
278
|
+
end
|
|
279
|
+
end
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
require 'librarian/source/git'
|
|
2
|
+
require 'librarian/puppet/source/local'
|
|
3
|
+
|
|
4
|
+
module Librarian
|
|
5
|
+
module Source
|
|
6
|
+
class Git
|
|
7
|
+
class Repository
|
|
8
|
+
def hash_from(remote, reference)
|
|
9
|
+
branch_names = remote_branch_names[remote]
|
|
10
|
+
if branch_names.include?(reference)
|
|
11
|
+
reference = "#{remote}/#{reference}"
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
command = %W(rev-parse #{reference}^{commit} --quiet)
|
|
15
|
+
run!(command, :chdir => true).strip
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# Naming this method 'version' causes an exception to be raised.
|
|
19
|
+
def module_version
|
|
20
|
+
return '0.0.1' unless modulefile?
|
|
21
|
+
|
|
22
|
+
metadata = ::Puppet::ModuleTool::Metadata.new
|
|
23
|
+
::Puppet::ModuleTool::ModulefileReader.evaluate(metadata, modulefile)
|
|
24
|
+
|
|
25
|
+
metadata.version
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def dependencies
|
|
29
|
+
return {} unless modulefile?
|
|
30
|
+
|
|
31
|
+
metadata = ::Puppet::ModuleTool::Metadata.new
|
|
32
|
+
|
|
33
|
+
::Puppet::ModuleTool::ModulefileReader.evaluate(metadata, modulefile)
|
|
34
|
+
|
|
35
|
+
metadata.dependencies.inject({}) do |h, dependency|
|
|
36
|
+
name = dependency.instance_variable_get(:@full_module_name)
|
|
37
|
+
version = dependency.instance_variable_get(:@version_requirement)
|
|
38
|
+
h.update(name => version)
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def modulefile
|
|
43
|
+
File.join(path, 'Modulefile')
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def modulefile?
|
|
47
|
+
File.exists?(modulefile)
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
module Puppet
|
|
54
|
+
module Source
|
|
55
|
+
class Git < Librarian::Source::Git
|
|
56
|
+
include Local
|
|
57
|
+
|
|
58
|
+
def cache!
|
|
59
|
+
return vendor_checkout! if vendor_cached?
|
|
60
|
+
|
|
61
|
+
if environment.local?
|
|
62
|
+
raise Error, "Could not find a local copy of #{uri} at #{sha}."
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
super
|
|
66
|
+
|
|
67
|
+
cache_in_vendor(repository.path) if environment.vendor?
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def vendor_tgz
|
|
71
|
+
environment.vendor_source + "#{sha}.tar.gz"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def vendor_cached?
|
|
75
|
+
vendor_tgz.exist?
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def vendor_checkout!
|
|
79
|
+
repository.path.rmtree if repository.path.exist?
|
|
80
|
+
repository.path.mkpath
|
|
81
|
+
|
|
82
|
+
Dir.chdir(repository.path.to_s) do
|
|
83
|
+
%x{tar xzf #{vendor_tgz}}
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
repository_cached!
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def cache_in_vendor(tmp_path)
|
|
90
|
+
Dir.chdir(tmp_path.to_s) do
|
|
91
|
+
%x{git archive #{sha} | gzip > #{vendor_tgz}}
|
|
92
|
+
end
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def fetch_version(name, extra)
|
|
96
|
+
cache!
|
|
97
|
+
found_path = found_path(name)
|
|
98
|
+
repository.module_version
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def fetch_dependencies(name, version, extra)
|
|
102
|
+
repository.dependencies.map do |k, v|
|
|
103
|
+
Dependency.new(k, v, forge_source)
|
|
104
|
+
end
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def forge_source
|
|
108
|
+
Forge.from_lock_options(environment, :remote=>"http://forge.puppetlabs.com")
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
end
|
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
require 'uri'
|
|
2
|
+
require 'net/https'
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
module Librarian
|
|
6
|
+
module Puppet
|
|
7
|
+
module Source
|
|
8
|
+
class GitHubTarball
|
|
9
|
+
class Repo
|
|
10
|
+
|
|
11
|
+
attr_accessor :source, :name
|
|
12
|
+
private :source=, :name=
|
|
13
|
+
|
|
14
|
+
def initialize(source, name)
|
|
15
|
+
self.source = source
|
|
16
|
+
self.name = name
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def versions
|
|
20
|
+
data = api_call("/repos/#{source.uri}/tags")
|
|
21
|
+
if data.nil?
|
|
22
|
+
raise Error, "Unable to find module '#{source.uri}' on https://github.com"
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
all_versions = data.map { |r| r['name'] }.sort.reverse
|
|
26
|
+
all_versions.reject { |version| version =~ /^v/ }.compact
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def manifests
|
|
30
|
+
versions.map do |version|
|
|
31
|
+
Manifest.new(source, name, version)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def install_version!(version, install_path)
|
|
36
|
+
if environment.local? && !vendored?(source.uri, version)
|
|
37
|
+
raise Error, "Could not find a local copy of #{source.uri} at #{version}."
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
vendor_cache(source.uri, version) unless vendored?(source.uri, version)
|
|
41
|
+
|
|
42
|
+
cache_version_unpacked! version
|
|
43
|
+
|
|
44
|
+
if install_path.exist?
|
|
45
|
+
install_path.rmtree
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
unpacked_path = version_unpacked_cache_path(version).children.first
|
|
49
|
+
FileUtils.cp_r(unpacked_path, install_path)
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def environment
|
|
53
|
+
source.environment
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def cache_path
|
|
57
|
+
@cache_path ||= source.cache_path.join(name)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def version_unpacked_cache_path(version)
|
|
61
|
+
cache_path.join('version').join(hexdigest(version.to_s))
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def hexdigest(value)
|
|
65
|
+
Digest::MD5.hexdigest(value)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def cache_version_unpacked!(version)
|
|
69
|
+
path = version_unpacked_cache_path(version)
|
|
70
|
+
return if path.directory?
|
|
71
|
+
|
|
72
|
+
path.mkpath
|
|
73
|
+
|
|
74
|
+
target = vendored?(source.uri, version) ? vendored_path(source.uri, version) : name
|
|
75
|
+
|
|
76
|
+
`tar xzf #{target} -C #{path}`
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def vendored?(name, version)
|
|
80
|
+
vendored_path(name, version).exist?
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def vendored_path(name, version)
|
|
84
|
+
environment.vendor_cache.mkpath
|
|
85
|
+
environment.vendor_cache.join("#{name.sub("/", "-")}-#{version}.tar.gz")
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def vendor_cache(name, version)
|
|
89
|
+
clean_up_old_cached_versions(name)
|
|
90
|
+
|
|
91
|
+
url = "https://api.github.com/repos/#{name}/tarball/#{version}"
|
|
92
|
+
url << "?access_token=#{ENV['GITHUB_API_TOKEN']}" if ENV['GITHUB_API_TOKEN']
|
|
93
|
+
`curl #{url} -o #{vendored_path(name, version).to_s} -L 2>&1`
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def clean_up_old_cached_versions(name)
|
|
97
|
+
Dir["#{environment.vendor_cache}/#{name.sub('/', '-')}*.tar.gz"].each do |old_version|
|
|
98
|
+
FileUtils.rm old_version
|
|
99
|
+
end
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
private
|
|
103
|
+
|
|
104
|
+
def api_call(path)
|
|
105
|
+
url = "https://api.github.com#{path}"
|
|
106
|
+
url << "?access_token=#{ENV['GITHUB_API_TOKEN']}" if ENV['GITHUB_API_TOKEN']
|
|
107
|
+
uri = URI.parse(url)
|
|
108
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
|
109
|
+
http.use_ssl = true
|
|
110
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
|
111
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
|
112
|
+
resp = http.request(request)
|
|
113
|
+
if resp.code.to_i != 200
|
|
114
|
+
nil
|
|
115
|
+
else
|
|
116
|
+
data = resp.body
|
|
117
|
+
JSON.parse(data)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
class << self
|
|
123
|
+
LOCK_NAME = 'GITHUBTARBALL'
|
|
124
|
+
|
|
125
|
+
def lock_name
|
|
126
|
+
LOCK_NAME
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
def from_lock_options(environment, options)
|
|
130
|
+
new(environment, options[:remote], options.reject { |k, v| k == :remote })
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
def from_spec_args(environment, uri, options)
|
|
134
|
+
recognised_options = []
|
|
135
|
+
unrecognised_options = options.keys - recognised_options
|
|
136
|
+
unless unrecognised_options.empty?
|
|
137
|
+
raise Error, "unrecognised options: #{unrecognised_options.join(", ")}"
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
new(environment, uri, options)
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
attr_accessor :environment
|
|
145
|
+
private :environment=
|
|
146
|
+
attr_reader :uri
|
|
147
|
+
|
|
148
|
+
def initialize(environment, uri, options = {})
|
|
149
|
+
self.environment = environment
|
|
150
|
+
@uri = uri
|
|
151
|
+
@cache_path = nil
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def to_s
|
|
155
|
+
uri
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def ==(other)
|
|
159
|
+
other &&
|
|
160
|
+
self.class == other.class &&
|
|
161
|
+
self.uri == other.uri
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def to_spec_args
|
|
165
|
+
[uri, {}]
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def to_lock_options
|
|
169
|
+
{:remote => uri}
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def pinned?
|
|
173
|
+
false
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
def unpin!
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def install!(manifest)
|
|
180
|
+
manifest.source == self or raise ArgumentError
|
|
181
|
+
|
|
182
|
+
name = manifest.name
|
|
183
|
+
version = manifest.version
|
|
184
|
+
install_path = install_path(name)
|
|
185
|
+
repo = repo(name)
|
|
186
|
+
|
|
187
|
+
repo.install_version! version, install_path
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def manifest(name, version, dependencies)
|
|
191
|
+
manifest = Manifest.new(self, name)
|
|
192
|
+
manifest.version = version
|
|
193
|
+
manifest.dependencies = dependencies
|
|
194
|
+
manifest
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def cache_path
|
|
198
|
+
@cache_path ||= begin
|
|
199
|
+
dir = Digest::MD5.hexdigest(uri)
|
|
200
|
+
environment.cache_path.join("source/puppet/githubtarball/#{dir}")
|
|
201
|
+
end
|
|
202
|
+
end
|
|
203
|
+
|
|
204
|
+
def install_path(name)
|
|
205
|
+
environment.install_path.join(name.split('/').last)
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
def fetch_version(name, version_uri)
|
|
209
|
+
versions = repo(name).versions
|
|
210
|
+
if versions.include? version_uri
|
|
211
|
+
version_uri
|
|
212
|
+
else
|
|
213
|
+
versions.first
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def fetch_dependencies(name, version, version_uri)
|
|
218
|
+
{}
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def manifests(name)
|
|
222
|
+
repo(name).manifests
|
|
223
|
+
end
|
|
224
|
+
|
|
225
|
+
private
|
|
226
|
+
|
|
227
|
+
def repo(name)
|
|
228
|
+
@repo ||= {}
|
|
229
|
+
@repo[name] ||= Repo.new(self, name)
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
end
|