Class: DependencyChecker::Runner

Inherits:
Object
  • Object
show all
Defined in:
lib/dependency_checker/runner.rb

Overview

rubocop:disable Metrics/ClassLength

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(verbose = false, forge_hostname = nil, forge_token = nil) ⇒ Runner

Returns a new instance of Runner.



14
15
16
17
# File 'lib/dependency_checker/runner.rb', line 14

def initialize(verbose = false, forge_hostname = nil, forge_token = nil)
  @forge   = DependencyChecker::ForgeHelper.new({}, forge_hostname, forge_token)
  @verbose = verbose
end

Instance Attribute Details

#problemsObject (readonly)

Returns the value of attribute problems.



12
13
14
# File 'lib/dependency_checker/runner.rb', line 12

def problems
  @problems
end

Instance Method Details

#check_module_exists(module_name) ⇒ Boolean

Check with forge if a specified module exists

Parameters:

  • module_name (String)

Returns:

  • (Boolean)

    boolean based on whether the module exists or not



65
66
67
# File 'lib/dependency_checker/runner.rb', line 65

def check_module_exists(module_name)
  @forge.check_module_exists(module_name)
end

#get_dependencies(module_name) ⇒ Map

Get dependencies of a supplied module name to verify if the depedencies are satisfied

Parameters:

  • module_name (String)

    name of module

Returns:

  • (Map)

    a map of dependencies along with their constraint, current version and whether they satisfy the constraint



140
141
142
143
144
# File 'lib/dependency_checker/runner.rb', line 140

def get_dependencies(module_name)
  module_data = @forge.get_module_data(module_name)
   = module_data.current_release.
  ()
end

#get_dependencies_from_metadata(metadata) ⇒ Map

Get dependencies of supplied module metadata. Takes module ovveride into account.

Parameters:

  • metadata (Hash)

    module metadata

Returns:

  • (Map)

    a map of dependencies along with their constraint, current version and whether they satisfy the constraint



157
158
159
160
# File 'lib/dependency_checker/runner.rb', line 157

def ()
  checker = DependencyChecker::MetadataChecker.new(, @forge, @updated_module, @updated_module_version)
  checker.check_dependencies
end

#get_dependencies_from_path(metadata_path) ⇒ Map

Get dependencies of a supplied module from a metadata.json file to verify if the depedencies are satisfied

Parameters:

  • metadata_path (String)

    path to metadata.json

Returns:

  • (Map)

    a map of dependencies along with their constraint, current version and whether they satisfy the constraint



149
150
151
152
# File 'lib/dependency_checker/runner.rb', line 149

def get_dependencies_from_path()
   = JSON.parse(File.read(), symbolize_names: true)
  ()
end

#get_name_from_metadata(metadata_path) ⇒ Map

Get dependencies of a supplied module from a metadata.json file to verify if the depedencies are satisfied

Parameters:

  • metadata_path (String)

    path to metadata.json

Returns:

  • (Map)

    a map of dependencies along with their constraint, current version and whether they satisfy the constraint



165
166
167
168
# File 'lib/dependency_checker/runner.rb', line 165

def ()
   = JSON.parse(File.read(), symbolize_names: true)
  [:name]
end

#override=(override) ⇒ Object



32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/dependency_checker/runner.rb', line 32

def override=(override)
  return unless override.is_a? Array

  @updated_module, @updated_module_version = override

  raise '*Error:* Pass an override in the form `--override module,version`' unless override.size == 2
  unless check_module_exists(@updated_module)
    raise "*Error:* Could not find *#{@updated_module}* on Puppet Forge! Ensure updated_module argument is valid."
  end
  unless SemanticPuppet::Version.valid?(@updated_module_version)
    raise "*Error:* Verify semantic versioning syntax *#{@updated_module_version}* of updated_module_version argument."
  end

  puts "Overriding *#{@updated_module}* version with *#{@updated_module_version}*\n\n"
  return unless @forge.check_module_deprecated(@updated_module)

  puts "The module you are comparing against *#{@updated_module}* is *deprecated*.\n\n"
end

#post(message) ⇒ Object

Post message to terminal

Parameters:

  • message (String)


201
202
203
# File 'lib/dependency_checker/runner.rb', line 201

def post(message)
  puts message
end

#resolve_from_files(metadata_files) ⇒ Object



27
28
29
30
# File 'lib/dependency_checker/runner.rb', line 27

def resolve_from_files()
  @use_local_files = true
  @modules         = Array() # should already be an array, but just in case
end

#resolve_from_namespace(namespace, endorsement) ⇒ Object



19
20
21
# File 'lib/dependency_checker/runner.rb', line 19

def resolve_from_namespace(namespace, endorsement)
  @modules = @forge.modules_in_namespace(namespace, endorsement)
end

#resolve_from_path(path) ⇒ Object



23
24
25
# File 'lib/dependency_checker/runner.rb', line 23

def resolve_from_path(path)
  @modules = return_modules(path)
end

#return_modules(path) ⇒ Array

Retrieve the array of module names from the supplied filename/URL

Returns:

  • (Array)

    an array of module names



172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/dependency_checker/runner.rb', line 172

def return_modules(path)
  begin
    # We use URI#open because it can handle file or URI paths.
    # This usage does not expose a security risk
    contents = URI.open(path).read # rubocop:disable Security/Open
  rescue Errno::ENOENT, SocketError
    raise "*Error:* Ensure *#{path}* is a valid file path or URL"
  end

  begin
    modules = if path.end_with? '.json'
                JSON.parse(contents)
              else
                YAML.safe_load(contents)
              end
  rescue StandardError
    raise "*Error:* Ensure syntax of #{path} file is valid YAML or JSON"
  end

  # transform from CAT supported module hash to simple list
  if path.end_with? '/content-and-tooling-team/modules/list.json'
    modules.filter_map { |key, _val| key['name'] } if modules.is_a? Array
  elsif modules.is_a? Hash
    modules.filter_map { |_key, val| val['puppet_module'] }
  end
end

#runObject



51
52
53
54
55
56
57
58
59
60
# File 'lib/dependency_checker/runner.rb', line 51

def run
  puts "_*Starting dependency checks...*_\n\n"

  # Post results of dependency checks
  message = run_dependency_checks
  @problems = message.size
  message = 'All modules have valid dependencies.' if message.empty?

  post(message)
end

#run_dependency_checksObject

Perform dependency checks on modules supplied by @modules



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
# File 'lib/dependency_checker/runner.rb', line 70

def run_dependency_checks
  # Cross reference dependencies from managed_modules file with @updated_module and @updated_module_version
  messages = Parallel.map(@modules) do |module_path|
    module_name = @use_local_files ? (module_path) : module_path
    mod_message = "Checking *#{module_path}* dependencies.\n"
    exists_on_forge = true

    # Check module_path is valid
    unless check_module_exists(module_name)
      if @use_local_files
        exists_on_forge = false
      else
        mod_message += "\t*Error:* Could not find *#{module_name}* on Puppet Forge! Ensure the module exists.\n\n"
        next mod_message
      end
    end

    # Fetch module dependencies

    dependencies = @use_local_files ? get_dependencies_from_path(module_path) : get_dependencies(module_name)

    # Post warning if module_path is deprecated
    mod_deprecated = exists_on_forge ? @forge.check_module_deprecated(module_name) : false
    mod_message += "\t*Warning:* *#{module_name}* is *deprecated*.\n" if mod_deprecated

    if dependencies.empty?
      mod_message += "\tNo dependencies listed\n\n"
      next mod_message if @verbose && !mod_deprecated
    end

    # Check each dependency to see if the latest version matchs the current modules' dependency constraints
    all_match = true
    dependencies.each do |dependency, constraint, current, satisfied|
      if satisfied && @verbose
        mod_message += "\t#{dependency} (#{constraint}) *matches* #{current}\n"
      elsif !satisfied
        all_match = false
        mod_message += "\t#{dependency} (#{constraint}) *doesn't match* #{current}\n"
      end

      if @forge.check_module_deprecated(dependency)
        all_match = false
        mod_message += "\t\t*Warning:* *#{dependency}* is *deprecated*.\n"
      end

      found_deprecation = true if @forge.check_module_deprecated(dependency)

      # Post warning if dependency is deprecated
      mod_message += "\tThe dependency module *#{dependency}* is *deprecated*.\n" if found_deprecation
    end

    mod_message += "\tAll dependencies match\n" if all_match
    mod_message += "\n"

    # If @verbose is true, always post message
    # If @verbose is false, only post if all dependencies don't match and/or if a dependency is deprecated
    all_match && !@verbose ? '' : mod_message
  end

  message = ''
  messages.each do |result|
    message += result
  end

  message
end