puppetfile-resolver 0.4.0 → 0.6.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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