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.
@@ -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 : Array of paths
15
- # strict_mode : [Boolean] Whether missing dependencies throw an error (default: false)
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
- # TODO: This default crap should move to the resolve class and we just validate (and raise) here
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, @puppet_module_paths, dependency, @cache, @resolver_ui) }
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
- DEFAULT_FORGE_URI ||= 'https://forgeapi.puppet.com'
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, forge_api_url = DEFAULT_FORGE_URI, resolver_ui, &block)
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("#{forge_api_url}/v3/releases")
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
- http_options = { :use_ssl => uri.class == URI::HTTPS }
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
- Net::HTTP.start(uri.host, uri.port, http_options) do |http|
56
- request = Net::HTTP::Get.new uri
57
- response = http.request request
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
- raise "Expected HTTP Code 200, but received #{response.code} for URI #{uri}: #{response.inspect}" unless response.code == '200'
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("#{forge_api_url}#{reply['pagination']['next']}")
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 * 50}" if loops > 20
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
- # We _could_ git clone this, but it'll take too long. So for now, just
14
- # try and resolve github based repositories by crafting a URL
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
- repo_url = nil
17
- if puppetfile_module.remote.start_with?('git@github.com:')
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
- # TODO: symbolise_object should be in a Util namespace
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,
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PuppetfileResolver
4
+ module SpecSearchers
5
+ class GitConfiguration
6
+ attr_accessor :proxy, :clone_dir
7
+ end
8
+ end
9
+ end
@@ -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, puppet_module_paths, dependency, cache, resolver_ui)
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)
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module PuppetfileResolver
4
+ module SpecSearchers
5
+ class LocalConfiguration
6
+ attr_accessor :puppet_module_paths
7
+
8
+ def initialize
9
+ @puppet_module_paths = []
10
+ end
11
+ end
12
+ end
13
+ end
@@ -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
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PuppetfileResolver
4
- VERSION ||= '0.4.0'
4
+ VERSION ||= '0.6.1'
5
5
  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
- opts = { cache: cache, ui: ui, module_paths: options[:module_paths], allow_missing_modules: !options[:strict] }
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,9 @@
1
+ {
2
+ "name": "testfixture-test_module",
3
+ "version": "0.1.0",
4
+ "author": "testfixture",
5
+ "summary": "Skeleton module test fixture",
6
+ "license": "Apache-2.0",
7
+ "source": "http://localhost",
8
+ "dependencies": []
9
+ }
@@ -0,0 +1,9 @@
1
+ require 'webrick'
2
+ require 'webrick/httpproxy'
3
+
4
+ proxy = WEBrick::HTTPProxyServer.new Port: (ARGV[0].nil? ? 32768 : ARGV[0])
5
+
6
+ trap 'INT' do proxy.shutdown end
7
+ trap 'TERM' do proxy.shutdown end
8
+
9
+ proxy.start
@@ -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