puppetfile-resolver 0.4.0 → 0.6.1
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 -1
- data/lib/puppetfile-resolver/data/ruby_ca_certs.pem +640 -740
- data/lib/puppetfile-resolver/resolution_provider.rb +15 -8
- data/lib/puppetfile-resolver/resolver.rb +2 -1
- data/lib/puppetfile-resolver/spec_searchers/configuration.rb +21 -0
- data/lib/puppetfile-resolver/spec_searchers/forge.rb +17 -19
- data/lib/puppetfile-resolver/spec_searchers/forge_configuration.rb +17 -0
- data/lib/puppetfile-resolver/spec_searchers/git/gclone.rb +82 -0
- data/lib/puppetfile-resolver/spec_searchers/git/github.rb +53 -0
- data/lib/puppetfile-resolver/spec_searchers/git/gitlab.rb +55 -0
- data/lib/puppetfile-resolver/spec_searchers/git.rb +16 -34
- data/lib/puppetfile-resolver/spec_searchers/git_configuration.rb +9 -0
- data/lib/puppetfile-resolver/spec_searchers/local.rb +3 -2
- data/lib/puppetfile-resolver/spec_searchers/local_configuration.rb +13 -0
- data/lib/puppetfile-resolver/util.rb +43 -0
- data/lib/puppetfile-resolver/version.rb +1 -1
- data/puppetfile-cli.rb +14 -1
- data/spec/fixtures/modulepath/test_module/README.md +1 -0
- data/spec/fixtures/modulepath/test_module/metadata.json +9 -0
- data/spec/fixtures/proxy.rb +9 -0
- data/spec/integration/deprecation_spec.rb +32 -0
- data/spec/integration/kitchensink_spec.rb +49 -0
- data/spec/integration/proxy_spec.rb +91 -0
- data/spec/spec_helper.rb +2 -0
- data/spec/unit/puppetfile-resolver/resolver_spec.rb +1 -1
- data/spec/unit/puppetfile-resolver/spec_searchers/git/gclone_spec.rb +49 -0
- metadata +28 -7
@@ -5,27 +5,34 @@ require 'puppetfile-resolver/cache/base'
|
|
5
5
|
require 'puppetfile-resolver/spec_searchers/forge'
|
6
6
|
require 'puppetfile-resolver/spec_searchers/git'
|
7
7
|
require 'puppetfile-resolver/spec_searchers/local'
|
8
|
+
require 'puppetfile-resolver/spec_searchers/configuration'
|
8
9
|
|
9
10
|
module PuppetfileResolver
|
10
11
|
class ResolutionProvider
|
11
12
|
include Molinillo::SpecificationProvider
|
12
13
|
|
13
14
|
# options
|
14
|
-
# module_paths
|
15
|
-
# strict_mode
|
15
|
+
# module_paths : Array of paths (Deprecated)
|
16
|
+
# strict_mode : [Boolean] Whether missing dependencies throw an error (default: false)
|
17
|
+
# spec_searcher_configuration : PuppetfileResolver::SpecSearchers::Configuration
|
16
18
|
def initialize(puppetfile_document, puppet_version, resolver_ui, options = {})
|
17
19
|
require 'semantic_puppet'
|
18
20
|
|
19
21
|
@puppetfile_document = puppetfile_document
|
20
22
|
raise 'The UI object must be of type Molinillo::UI' if resolver_ui.nil? || !resolver_ui.is_a?(Molinillo::UI)
|
21
23
|
@resolver_ui = resolver_ui
|
22
|
-
|
23
|
-
@puppet_module_paths = options[:module_paths].nil? ? [] : options[:module_paths]
|
24
|
+
@spec_searcher_configuration = options[:spec_searcher_configuration] || PuppetfileResolver::SpecSearchers::Configuration.new
|
24
25
|
@allow_missing_modules = options[:allow_missing_modules].nil? ? true : options[:allow_missing_modules] == true
|
25
26
|
# There can be only one puppet specification in existance so we pre-load here.
|
26
27
|
@puppet_specification = Models::PuppetSpecification.new(puppet_version)
|
27
28
|
@module_info = {}
|
28
29
|
@cache = options[:cache].nil? ? Cache::Base.new : options[:cache]
|
30
|
+
|
31
|
+
# Check for deprecated options
|
32
|
+
unless options[:module_paths].nil? # rubocop:disable Style/GuardClause
|
33
|
+
Warning.warn 'The use of the module_paths option has been deprecated'
|
34
|
+
@spec_searcher_configuration.local.puppet_module_paths = options[:module_paths]
|
35
|
+
end
|
29
36
|
end
|
30
37
|
|
31
38
|
# Search for the specifications that match the given dependency.
|
@@ -137,9 +144,9 @@ module PuppetfileResolver
|
|
137
144
|
unless mod.nil?
|
138
145
|
case mod.module_type
|
139
146
|
when Puppetfile::FORGE_MODULE
|
140
|
-
@module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Forge.find_all(dependency, @cache, @resolver_ui) }
|
147
|
+
@module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Forge.find_all(dependency, @cache, @resolver_ui, @spec_searcher_configuration.forge) }
|
141
148
|
when Puppetfile::GIT_MODULE
|
142
|
-
@module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Git.find_all(mod, dependency, @cache, @resolver_ui) }
|
149
|
+
@module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Git.find_all(mod, dependency, @cache, @resolver_ui, @spec_searcher_configuration.git) }
|
143
150
|
else # rubocop:disable Style/EmptyElse
|
144
151
|
# Errr.... Nothing
|
145
152
|
end
|
@@ -147,13 +154,13 @@ module PuppetfileResolver
|
|
147
154
|
return @module_info[dependency.name] unless @module_info[dependency.name].empty?
|
148
155
|
|
149
156
|
# It's not in the Puppetfile, so perhaps it's in our modulepath?
|
150
|
-
@module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Local.find_all(mod,
|
157
|
+
@module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Local.find_all(mod, dependency, @cache, @resolver_ui, @spec_searcher_configuration.local) }
|
151
158
|
return @module_info[dependency.name] unless @module_info[dependency.name].empty?
|
152
159
|
|
153
160
|
# It's not in the Puppetfile and not on disk, so perhaps it's on the Forge?
|
154
161
|
# The forge needs an owner and name to be able to resolve
|
155
162
|
if dependency.name && dependency.owner # rubocop:disable Style/IfUnlessModifier
|
156
|
-
@module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Forge.find_all(dependency, @cache, @resolver_ui) }
|
163
|
+
@module_info[dependency.name] = safe_spec_search(dependency) { SpecSearchers::Forge.find_all(dependency, @cache, @resolver_ui, @spec_searcher_configuration.forge) }
|
157
164
|
end
|
158
165
|
|
159
166
|
# If we can't find any specifications for the module and we're allowing missing modules
|
@@ -20,7 +20,8 @@ module PuppetfileResolver
|
|
20
20
|
|
21
21
|
# options
|
22
22
|
# :cache => Cache Object
|
23
|
-
# :module_paths => Array[String]
|
23
|
+
# :module_paths => Array[String] (Deprecated)
|
24
|
+
# :spec_searcher_configuration => PuppetfileResolver::SpecSearchers::Configuration
|
24
25
|
def resolve(options = {})
|
25
26
|
if options[:ui]
|
26
27
|
raise 'The UI object must be of type Molinillo::UI' unless options[:ui].is_a?(Molinillo::UI)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'puppetfile-resolver/spec_searchers/forge_configuration'
|
4
|
+
require 'puppetfile-resolver/spec_searchers/git_configuration'
|
5
|
+
require 'puppetfile-resolver/spec_searchers/local_configuration'
|
6
|
+
|
7
|
+
module PuppetfileResolver
|
8
|
+
module SpecSearchers
|
9
|
+
class Configuration
|
10
|
+
attr_reader :local
|
11
|
+
attr_reader :forge
|
12
|
+
attr_reader :git
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@local = LocalConfiguration.new
|
16
|
+
@forge = ForgeConfiguration.new
|
17
|
+
@git = GitConfiguration.new
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,6 +1,8 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'puppetfile-resolver/util'
|
3
4
|
require 'puppetfile-resolver/spec_searchers/common'
|
5
|
+
require 'puppetfile-resolver/spec_searchers/forge_configuration'
|
4
6
|
require 'uri'
|
5
7
|
require 'net/http'
|
6
8
|
require 'openssl'
|
@@ -9,9 +11,7 @@ require 'json'
|
|
9
11
|
module PuppetfileResolver
|
10
12
|
module SpecSearchers
|
11
13
|
module Forge
|
12
|
-
|
13
|
-
|
14
|
-
def self.find_all(dependency, cache, resolver_ui)
|
14
|
+
def self.find_all(dependency, cache, resolver_ui, config)
|
15
15
|
dep_id = ::PuppetfileResolver::SpecSearchers::Common.dependency_cache_id(self, dependency)
|
16
16
|
|
17
17
|
# Has the information been cached?
|
@@ -19,7 +19,7 @@ module PuppetfileResolver
|
|
19
19
|
|
20
20
|
result = []
|
21
21
|
# Query the forge
|
22
|
-
fetch_all_module_releases(dependency.owner, dependency.name, resolver_ui) do |partial_releases|
|
22
|
+
fetch_all_module_releases(dependency.owner, dependency.name, resolver_ui, config) do |partial_releases|
|
23
23
|
partial_releases.each do |release|
|
24
24
|
result << Models::ModuleSpecification.new(
|
25
25
|
name: release['module']['name'],
|
@@ -35,38 +35,36 @@ module PuppetfileResolver
|
|
35
35
|
result
|
36
36
|
end
|
37
37
|
|
38
|
-
def self.fetch_all_module_releases(owner, name,
|
38
|
+
def self.fetch_all_module_releases(owner, name, resolver_ui, config, &block)
|
39
39
|
raise 'Requires a block to yield' unless block
|
40
|
-
uri = ::URI.parse("#{
|
40
|
+
uri = ::URI.parse("#{config.forge_api}/v3/releases")
|
41
41
|
params = { :module => "#{owner}-#{name}", :exclude_fields => 'readme changelog license reference tasks', :limit => 50 }
|
42
42
|
uri.query = ::URI.encode_www_form(params)
|
43
43
|
|
44
44
|
loops = 0
|
45
45
|
loop do
|
46
46
|
resolver_ui.debug { "Querying the forge for a module with #{uri}" }
|
47
|
-
|
48
|
-
|
49
|
-
# Because on Windows Ruby doesn't use the Windows certificate store which has up-to date
|
50
|
-
# CA certs, we can't depend on someone setting the environment variable correctly. So use our
|
51
|
-
# static CA PEM file if SSL_CERT_FILE is not set.
|
52
|
-
http_options[:ca_file] = PuppetfileResolver::Util.static_ca_cert_file if ENV['SSL_CERT_FILE'].nil?
|
53
|
-
|
47
|
+
err_msg = "Unable to find module #{owner}-#{name} on #{config.forge_api}"
|
48
|
+
err_msg += config.proxy ? " with proxy #{config.proxy}: " : ': '
|
54
49
|
response = nil
|
55
|
-
|
56
|
-
|
57
|
-
response =
|
50
|
+
|
51
|
+
begin
|
52
|
+
response = ::PuppetfileResolver::Util.net_http_get(uri, config.proxy)
|
53
|
+
rescue ::StandardError => e
|
54
|
+
raise err_msg + e.message
|
58
55
|
end
|
59
|
-
|
56
|
+
|
57
|
+
raise err_msg + "Expected HTTP Code 200, but received #{response.code}" unless response.code == '200'
|
60
58
|
|
61
59
|
reply = ::JSON.parse(response.body)
|
62
60
|
yield reply['results']
|
63
61
|
|
64
62
|
break if reply['pagination'].nil? || reply['pagination']['next'].nil?
|
65
|
-
uri = ::URI.parse("#{
|
63
|
+
uri = ::URI.parse("#{config.forge_api}#{reply['pagination']['next']}")
|
66
64
|
|
67
65
|
# Circuit breaker in case the worst happens (max 1000 module releases)
|
68
66
|
loops += 1
|
69
|
-
raise "Too many Forge API requests #{loops
|
67
|
+
raise err_msg + "Too many Forge API requests #{loops}" if loops > 20
|
70
68
|
end
|
71
69
|
end
|
72
70
|
private_class_method :fetch_all_module_releases
|
@@ -0,0 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module PuppetfileResolver
|
4
|
+
module SpecSearchers
|
5
|
+
class ForgeConfiguration
|
6
|
+
DEFAULT_FORGE_URI ||= 'https://forgeapi.puppet.com'
|
7
|
+
|
8
|
+
def forge_api
|
9
|
+
@forge_api || DEFAULT_FORGE_URI
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_writer :forge_api
|
13
|
+
|
14
|
+
attr_accessor :proxy
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'tempfile'
|
4
|
+
require 'English'
|
5
|
+
require 'puppetfile-resolver/util'
|
6
|
+
require 'puppetfile-resolver/spec_searchers/common'
|
7
|
+
require 'puppetfile-resolver/spec_searchers/git_configuration'
|
8
|
+
require 'puppetfile-resolver/util'
|
9
|
+
require 'uri'
|
10
|
+
|
11
|
+
module PuppetfileResolver
|
12
|
+
module SpecSearchers
|
13
|
+
module Git
|
14
|
+
module GClone
|
15
|
+
# @summary clones the remote url and reads the metadata file
|
16
|
+
# @returns [String] the content of the metadata file
|
17
|
+
def self.metadata(puppetfile_module, resolver_ui, config)
|
18
|
+
repo_url = puppetfile_module.remote
|
19
|
+
|
20
|
+
unless PuppetfileResolver::Util.git?
|
21
|
+
resolver_ui.debug { 'Git executible not found, unable to use git clone resolution' }
|
22
|
+
|
23
|
+
return nil
|
24
|
+
end
|
25
|
+
return nil if repo_url.nil?
|
26
|
+
return nil unless valid_http_url?(repo_url)
|
27
|
+
|
28
|
+
metadata_file = 'metadata.json'
|
29
|
+
|
30
|
+
ref = puppetfile_module.ref ||
|
31
|
+
puppetfile_module.tag ||
|
32
|
+
puppetfile_module.commit ||
|
33
|
+
puppetfile_module.branch ||
|
34
|
+
'HEAD'
|
35
|
+
|
36
|
+
resolver_ui.debug { "Querying git repository #{repo_url}" }
|
37
|
+
|
38
|
+
clone_and_read_file(repo_url, ref, metadata_file, config)
|
39
|
+
end
|
40
|
+
|
41
|
+
# @summary clones the git url and reads the file at the given ref
|
42
|
+
# a temp directory will be created and then destroyed during
|
43
|
+
# the cloning and reading process
|
44
|
+
# @param ref [String] the git ref, branch, commit, tag
|
45
|
+
# @param file [String] the file you wish to read
|
46
|
+
# @returns [String] the content of the file
|
47
|
+
def self.clone_and_read_file(url, ref, file, config)
|
48
|
+
clone_cmd = ['git', 'clone', '--bare', '--depth=1', '--single-branch']
|
49
|
+
err_msg = ''
|
50
|
+
if config.proxy
|
51
|
+
err_msg += " with proxy #{config.proxy}: "
|
52
|
+
proxy = "--config \"http.proxy=#{config.proxy}\" --config \"https.proxy=#{config.proxy}\""
|
53
|
+
clone_cmd.push(proxy)
|
54
|
+
end
|
55
|
+
|
56
|
+
Dir.mktmpdir(nil, config.clone_dir) do |dir|
|
57
|
+
clone_cmd.push("--branch=#{ref}") if ref != 'HEAD'
|
58
|
+
clone_cmd.push(url, dir)
|
59
|
+
out, err_out, process = ::PuppetfileResolver::Util.run_command(clone_cmd)
|
60
|
+
err_msg += out
|
61
|
+
raise err_msg unless process.success?
|
62
|
+
Dir.chdir(dir) do
|
63
|
+
content, err_out, process = ::PuppetfileResolver::Util.run_command(['git', 'show', "#{ref}:#{file}"])
|
64
|
+
raise 'InvalidContent' unless process.success? && content.length > 2
|
65
|
+
return content
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def self.valid_http_url?(url)
|
71
|
+
# uri does not work with git urls, return true
|
72
|
+
return true if url.start_with?('git@')
|
73
|
+
|
74
|
+
uri = URI.parse(url)
|
75
|
+
uri.is_a?(URI::HTTP) && !uri.host.nil?
|
76
|
+
rescue URI::InvalidURIError
|
77
|
+
false
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'puppetfile-resolver/util'
|
4
|
+
require 'puppetfile-resolver/spec_searchers/common'
|
5
|
+
require 'puppetfile-resolver/spec_searchers/git_configuration'
|
6
|
+
|
7
|
+
module PuppetfileResolver
|
8
|
+
module SpecSearchers
|
9
|
+
module Git
|
10
|
+
module GitHub
|
11
|
+
def self.metadata(puppetfile_module, resolver_ui, config)
|
12
|
+
repo_url = nil
|
13
|
+
if puppetfile_module.remote.start_with?('git@github.com:')
|
14
|
+
repo_url = puppetfile_module.remote.slice(15..-1)
|
15
|
+
repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
|
16
|
+
elsif puppetfile_module.remote.start_with?('https://github.com/')
|
17
|
+
repo_url = puppetfile_module.remote.slice(19..-1)
|
18
|
+
repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
|
19
|
+
end
|
20
|
+
return nil if repo_url.nil?
|
21
|
+
|
22
|
+
metadata_url = 'https://raw.githubusercontent.com/' + repo_url + '/'
|
23
|
+
if puppetfile_module.ref
|
24
|
+
metadata_url += puppetfile_module.ref + '/'
|
25
|
+
elsif puppetfile_module.tag
|
26
|
+
metadata_url += puppetfile_module.tag + '/'
|
27
|
+
else
|
28
|
+
# Default to master. Should it raise?
|
29
|
+
metadata_url += 'master/'
|
30
|
+
end
|
31
|
+
metadata_url += 'metadata.json'
|
32
|
+
|
33
|
+
resolver_ui.debug { "Querying GitHub with #{metadata_url}" }
|
34
|
+
err_msg = "Unable to find module at #{puppetfile_module.remote}"
|
35
|
+
err_msg += config.proxy ? " with proxy #{config.proxy}: " : ': '
|
36
|
+
response = nil
|
37
|
+
|
38
|
+
begin
|
39
|
+
response = ::PuppetfileResolver::Util.net_http_get(metadata_url, config.proxy)
|
40
|
+
rescue ::StandardError => e
|
41
|
+
raise err_msg + e.message
|
42
|
+
end
|
43
|
+
|
44
|
+
if response.code != '200'
|
45
|
+
resolver_ui.debug(err_msg + "Expected HTTP Code 200, but received #{response.code}")
|
46
|
+
return nil
|
47
|
+
end
|
48
|
+
response.body
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'puppetfile-resolver/util'
|
4
|
+
require 'puppetfile-resolver/spec_searchers/common'
|
5
|
+
require 'puppetfile-resolver/spec_searchers/git_configuration'
|
6
|
+
|
7
|
+
module PuppetfileResolver
|
8
|
+
module SpecSearchers
|
9
|
+
module Git
|
10
|
+
module GitLab
|
11
|
+
def self.metadata(puppetfile_module, resolver_ui, config)
|
12
|
+
repo_url = nil
|
13
|
+
if puppetfile_module.remote.start_with?('git@gitlab.com:')
|
14
|
+
repo_url = puppetfile_module.remote.slice(15..-1)
|
15
|
+
repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
|
16
|
+
elsif puppetfile_module.remote.start_with?('https://gitlab.com/')
|
17
|
+
repo_url = puppetfile_module.remote.slice(19..-1)
|
18
|
+
repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
|
19
|
+
end
|
20
|
+
return nil if repo_url.nil?
|
21
|
+
|
22
|
+
# Example URL
|
23
|
+
# https://gitlab.com/simp/pupmod-simp-crypto_policy/-/raw/0.1.4/metadata.json
|
24
|
+
metadata_url = 'https://gitlab.com/' + repo_url + '/-/raw/'
|
25
|
+
if puppetfile_module.ref
|
26
|
+
metadata_url += puppetfile_module.ref + '/'
|
27
|
+
elsif puppetfile_module.tag
|
28
|
+
metadata_url += puppetfile_module.tag + '/'
|
29
|
+
else
|
30
|
+
# Default to master. Should it raise?
|
31
|
+
metadata_url += 'master/'
|
32
|
+
end
|
33
|
+
metadata_url += 'metadata.json'
|
34
|
+
|
35
|
+
resolver_ui.debug { "Querying GitLab with #{metadata_url}" }
|
36
|
+
err_msg = "Unable to find module at #{puppetfile_module.remote}"
|
37
|
+
err_msg += config.proxy ? " with proxy #{config.proxy}: " : ': '
|
38
|
+
response = nil
|
39
|
+
|
40
|
+
begin
|
41
|
+
response = ::PuppetfileResolver::Util.net_http_get(metadata_url, config.proxy)
|
42
|
+
rescue ::StandardError => e
|
43
|
+
raise err_msg + e.message
|
44
|
+
end
|
45
|
+
|
46
|
+
if response.code != '200'
|
47
|
+
resolver_ui.debug(err_msg + "Expected HTTP Code 200, but received #{response.code}")
|
48
|
+
return nil
|
49
|
+
end
|
50
|
+
response.body
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -1,53 +1,35 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'puppetfile-resolver/util'
|
3
4
|
require 'puppetfile-resolver/spec_searchers/common'
|
5
|
+
require 'puppetfile-resolver/spec_searchers/git_configuration'
|
6
|
+
require 'puppetfile-resolver/spec_searchers/git/github'
|
7
|
+
require 'puppetfile-resolver/spec_searchers/git/gitlab'
|
8
|
+
require 'puppetfile-resolver/spec_searchers/git/gclone'
|
4
9
|
|
5
10
|
module PuppetfileResolver
|
6
11
|
module SpecSearchers
|
7
12
|
module Git
|
8
|
-
def self.find_all(puppetfile_module, dependency, cache, resolver_ui)
|
13
|
+
def self.find_all(puppetfile_module, dependency, cache, resolver_ui, config)
|
9
14
|
dep_id = ::PuppetfileResolver::SpecSearchers::Common.dependency_cache_id(self, dependency)
|
10
15
|
# Has the information been cached?
|
11
16
|
return cache.load(dep_id) if cache.exist?(dep_id)
|
12
17
|
|
13
|
-
#
|
14
|
-
#
|
18
|
+
# The git clone method takes around (1s) depending on repo size. Not sure if the
|
19
|
+
# other methods take longer or shorter but I preserved the legacy code for now.
|
20
|
+
# Technically, the gclone class could replace the other classes and speed up
|
21
|
+
# this process here.
|
22
|
+
metadata = GitHub.metadata(puppetfile_module, resolver_ui, config) ||
|
23
|
+
GitLab.metadata(puppetfile_module, resolver_ui, config) ||
|
24
|
+
GClone.metadata(puppetfile_module, resolver_ui, config)
|
15
25
|
|
16
|
-
|
17
|
-
|
18
|
-
repo_url = puppetfile_module.remote.slice(15..-1)
|
19
|
-
repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
|
20
|
-
end
|
21
|
-
if puppetfile_module.remote.start_with?('https://github.com/')
|
22
|
-
repo_url = puppetfile_module.remote.slice(19..-1)
|
23
|
-
repo_url = repo_url.slice(0..-5) if repo_url.end_with?('.git')
|
24
|
-
end
|
25
|
-
|
26
|
-
return [] if repo_url.nil?
|
27
|
-
|
28
|
-
metadata_url = 'https://raw.githubusercontent.com/' + repo_url + '/'
|
29
|
-
if puppetfile_module.ref
|
30
|
-
metadata_url += puppetfile_module.ref + '/'
|
31
|
-
elsif puppetfile_module.tag
|
32
|
-
metadata_url += puppetfile_module.tag + '/'
|
33
|
-
else
|
34
|
-
# Default to master. Should it raise?
|
35
|
-
metadata_url += 'master/'
|
36
|
-
end
|
37
|
-
metadata_url += 'metadata.json'
|
38
|
-
|
39
|
-
require 'net/http'
|
40
|
-
require 'uri'
|
41
|
-
|
42
|
-
resolver_ui.debug { "Querying the Github with #{metadata_url}" }
|
43
|
-
response = Net::HTTP.get_response(URI.parse(metadata_url))
|
44
|
-
if response.code != '200'
|
26
|
+
if metadata.nil? || metadata.empty?
|
27
|
+
# Cache that we couldn't find the metadata
|
45
28
|
cache.save(dep_id, [])
|
46
29
|
return []
|
47
30
|
end
|
48
31
|
|
49
|
-
|
50
|
-
metadata = ::PuppetfileResolver::Util.symbolise_object(::JSON.parse(response.body))
|
32
|
+
metadata = ::PuppetfileResolver::Util.symbolise_object(::JSON.parse(metadata))
|
51
33
|
result = [Models::ModuleSpecification.new(
|
52
34
|
name: metadata[:name],
|
53
35
|
origin: :git,
|
@@ -1,18 +1,19 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require 'puppetfile-resolver/spec_searchers/common'
|
4
|
+
require 'puppetfile-resolver/spec_searchers/local_configuration'
|
4
5
|
|
5
6
|
module PuppetfileResolver
|
6
7
|
module SpecSearchers
|
7
8
|
module Local
|
8
|
-
def self.find_all(_puppetfile_module,
|
9
|
+
def self.find_all(_puppetfile_module, dependency, cache, resolver_ui, config)
|
9
10
|
dep_id = ::PuppetfileResolver::SpecSearchers::Common.dependency_cache_id(self, dependency)
|
10
11
|
# Has the information been cached?
|
11
12
|
return cache.load(dep_id) if cache.exist?(dep_id)
|
12
13
|
|
13
14
|
result = []
|
14
15
|
# Find the module in the modulepaths
|
15
|
-
puppet_module_paths.each do |module_path|
|
16
|
+
config.puppet_module_paths.each do |module_path|
|
16
17
|
next unless Dir.exist?(module_path)
|
17
18
|
module_dir = File.expand_path(File.join(module_path, dependency.name))
|
18
19
|
next unless Dir.exist?(module_dir)
|
@@ -1,5 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
+
require 'open3'
|
4
|
+
|
3
5
|
module PuppetfileResolver
|
4
6
|
module Util
|
5
7
|
def self.symbolise_object(object)
|
@@ -19,5 +21,46 @@ module PuppetfileResolver
|
|
19
21
|
def self.static_ca_cert_file
|
20
22
|
@static_ca_cert_file ||= File.expand_path(File.join(__dir__, 'data', 'ruby_ca_certs.pem'))
|
21
23
|
end
|
24
|
+
|
25
|
+
# Execute a HTTP/S GET query and return the response
|
26
|
+
# @param [String, URI] uri The URI to request
|
27
|
+
# @param [nil, String, URI] proxy The URI of the proxy server to use. Defaults to nil (No proxy server)
|
28
|
+
# @return [Net::HTTPResponse] the response of the request
|
29
|
+
def self.net_http_get(uri, proxy = nil)
|
30
|
+
uri = URI.parse(uri) unless uri.is_a?(URI)
|
31
|
+
|
32
|
+
http_options = { :use_ssl => uri.class == URI::HTTPS }
|
33
|
+
# Because on Windows Ruby doesn't use the Windows certificate store which has up-to date
|
34
|
+
# CA certs, we can't depend on someone setting the environment variable correctly. So use our
|
35
|
+
# static CA PEM file if SSL_CERT_FILE is not set.
|
36
|
+
http_options[:ca_file] = PuppetfileResolver::Util.static_ca_cert_file if ENV['SSL_CERT_FILE'].nil?
|
37
|
+
|
38
|
+
start_args = [uri.host, uri.port]
|
39
|
+
|
40
|
+
unless proxy.nil?
|
41
|
+
proxy = URI.parse(proxy) unless proxy.is_a?(URI)
|
42
|
+
start_args.concat([proxy.host, proxy.port, proxy.user, proxy.password])
|
43
|
+
end
|
44
|
+
|
45
|
+
Net::HTTP.start(*start_args, http_options) { |http| return http.request(Net::HTTP::Get.new(uri)) }
|
46
|
+
nil
|
47
|
+
end
|
48
|
+
|
49
|
+
# @summary runs the command on the shell
|
50
|
+
# @param cmd [Array] an array of command and args
|
51
|
+
# @returns [Array] the result of running the comand and the process
|
52
|
+
# @example run_command(['git', '--version'])
|
53
|
+
def self.run_command(cmd)
|
54
|
+
Open3.capture3(*cmd)
|
55
|
+
end
|
56
|
+
|
57
|
+
# @summary checks if git is installed and on the path
|
58
|
+
# @returns [Boolean] true if git is found in the path
|
59
|
+
def self.git?
|
60
|
+
Open3.capture3('git', '--version')
|
61
|
+
true
|
62
|
+
rescue Errno::ENOENT
|
63
|
+
false
|
64
|
+
end
|
22
65
|
end
|
23
66
|
end
|
data/puppetfile-cli.rb
CHANGED
@@ -18,6 +18,7 @@ class CommandLineParser
|
|
18
18
|
cache_dir: nil,
|
19
19
|
module_paths: [],
|
20
20
|
path: nil,
|
21
|
+
proxy: nil,
|
21
22
|
puppet_version: nil,
|
22
23
|
strict: false
|
23
24
|
}
|
@@ -41,6 +42,10 @@ class CommandLineParser
|
|
41
42
|
args[:debug] = true
|
42
43
|
end
|
43
44
|
|
45
|
+
opts.on('--proxy=PROXY_URL', 'HTTP/S Proxy server to use. For example http://localhost:8888') do |proxy|
|
46
|
+
args[:proxy] = proxy
|
47
|
+
end
|
48
|
+
|
44
49
|
opts.on('-s', '--strict', 'Do not allow missing dependencies. Default false which marks dependencies as missing and does not raise an error.') do
|
45
50
|
args[:strict] = true
|
46
51
|
end
|
@@ -88,7 +93,15 @@ if options[:debug]
|
|
88
93
|
else
|
89
94
|
ui = nil
|
90
95
|
end
|
91
|
-
|
96
|
+
|
97
|
+
config = PuppetfileResolver::SpecSearchers::Configuration.new
|
98
|
+
config.local.puppet_module_paths = options[:module_paths]
|
99
|
+
unless options[:proxy].nil?
|
100
|
+
config.git.proxy = options[:proxy]
|
101
|
+
config.forge.proxy = options[:proxy]
|
102
|
+
end
|
103
|
+
|
104
|
+
opts = { cache: cache, ui: ui, spec_searcher_configuration: config, allow_missing_modules: !options[:strict] }
|
92
105
|
|
93
106
|
# Resolve
|
94
107
|
result = resolver.resolve(opts)
|
@@ -0,0 +1 @@
|
|
1
|
+
This test fixture contains a valid module with classes, types and functions.
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
require 'puppetfile-resolver/resolver'
|
4
|
+
require 'puppetfile-resolver/puppetfile'
|
5
|
+
|
6
|
+
|
7
|
+
describe 'Depreaction Tests' do
|
8
|
+
context 'With module_paths option' do
|
9
|
+
it 'should resolve a complete Puppetfile' do
|
10
|
+
|
11
|
+
content = <<-PUPFILE
|
12
|
+
forge 'https://forge.puppet.com'
|
13
|
+
|
14
|
+
# Local module path module
|
15
|
+
mod 'testfixture/test_module', :latest
|
16
|
+
PUPFILE
|
17
|
+
|
18
|
+
puppetfile = ::PuppetfileResolver::Puppetfile::Parser::R10KEval.parse(content)
|
19
|
+
resolver = PuppetfileResolver::Resolver.new(puppetfile)
|
20
|
+
|
21
|
+
expect(Warning).to receive(:warn).with(/module_paths/).and_return(nil)
|
22
|
+
|
23
|
+
result = resolver.resolve({
|
24
|
+
allow_missing_modules: false,
|
25
|
+
module_paths: [File.join(FIXTURES_DIR, 'modulepath')]
|
26
|
+
})
|
27
|
+
|
28
|
+
expect(result.specifications).to include('test_module')
|
29
|
+
expect(result.specifications['test_module'].version.to_s).to eq('0.1.0')
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|