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



61
62
63
# File 'lib/dependency_checker/runner.rb', line 61

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



136
137
138
139
140
# File 'lib/dependency_checker/runner.rb', line 136

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



153
154
155
156
# File 'lib/dependency_checker/runner.rb', line 153

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



145
146
147
148
# File 'lib/dependency_checker/runner.rb', line 145

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



161
162
163
164
# File 'lib/dependency_checker/runner.rb', line 161

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
# 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
  raise "*Error:* Could not find *#{@updated_module}* on Puppet Forge! Ensure updated_module argument is valid." unless check_module_exists(@updated_module)
  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"
  puts "The module you are comparing against *#{@updated_module}* is *deprecated*.\n\n" if @forge.check_module_deprecated(@updated_module)
end

#post(message) ⇒ Object

Post message to terminal

Parameters:

  • message (String)


197
198
199
# File 'lib/dependency_checker/runner.rb', line 197

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



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

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



47
48
49
50
51
52
53
54
55
56
# File 'lib/dependency_checker/runner.rb', line 47

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



66
67
68
69
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
# File 'lib/dependency_checker/runner.rb', line 66

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