Class: DataParser
- Inherits:
-
Object
- Object
- DataParser
- Defined in:
- lib/puppet-check/data_parser.rb
Overview
executes diagnostics on data files
Class Method Summary collapse
-
.eyaml(files, public, private) ⇒ Object
checks eyaml (.eyaml/.eyml).
-
.hiera(data, file) ⇒ Object
checks hieradata.
-
.json(files) ⇒ Object
checks json (.json).
-
.yaml(files) ⇒ Object
checks yaml (.yaml/.yml).
Class Method Details
.eyaml(files, public, private) ⇒ Object
checks eyaml (.eyaml/.eyml)
28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/puppet-check/data_parser.rb', line 28 def self.eyaml(files, public, private) require 'openssl' # keys specified? if public.nil? || private.nil? PuppetCheck.settings[:ignored_files].concat(files) return warn 'Public X509 and/or Private RSA PKCS7 certs were not specified. EYAML checks will not be executed.' end # keys exist? unless File.file?(public) && File.file?(private) PuppetCheck.settings[:ignored_files].concat(files) return warn 'Specified Public X509 and/or Private RSA PKCS7 certs do not exist. EYAML checks will not be executed.' end # setup decryption rsa = OpenSSL::PKey::RSA.new(File.read(private)) x509 = OpenSSL::X509::Certificate.new(File.read(public)) files.each do |file| # grab all encoded portions of the eyaml # decrypt the encoded portions decrypted = OpenSSL::PKCS7.new(File.read(file)).decrypt(rsa, x509) # insert decrypted portions back into eyaml (pass into loader below) # check yaml syntax begin parsed = YAML.load_file(decrypted) rescue StandardError => err PuppetCheck.settings[:error_files].push("#{file}:\n#{err.to_s.gsub("(#{file}): ", '')}") else warnings = [] # perform some rudimentary hiera checks if data exists and is hieradata warnings = hiera(parsed, file) if parsed next PuppetCheck.settings[:warning_files].push("#{file}:\n#{warnings.join("\n")}") unless warnings.empty? PuppetCheck.settings[:clean_files].push(file.to_s) end end end |
.hiera(data, file) ⇒ Object
checks hieradata
203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 |
# File 'lib/puppet-check/data_parser.rb', line 203 def self.hiera(data, file) private_class_method :method warnings = [] # disregard nil/undef value data check if default values (common) unless file =~ /^common/ data.each do |key, value| # check for nil values in the data (nil keys are fine) if (value.is_a?(Hash) && value.values.any?(&:nil?)) || value.nil? warnings.push("Value(s) missing in key '#{key}'.") end end end # check that '---' does not show up more than once in the hieradata warnings.push('The string --- appears more than once in this data and Hiera may fail to parse it correctly.') if File.read(file).scan(/---/).count >= 2 warnings end |
.json(files) ⇒ Object
checks json (.json)
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 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 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 194 195 196 197 198 199 200 |
# File 'lib/puppet-check/data_parser.rb', line 73 def self.json(files) require 'json' files.each do |file| # check json syntax begin parsed = JSON.parse(File.read(file)) rescue JSON::ParserError => err PuppetCheck.settings[:error_files].push("#{file}:\n#{err.to_s.lines.first.strip}") else warnings = [] # check metadata.json if File.basename(file) == 'metadata.json' # metadata-json-lint has issues and is essentially no longer maintained, so here is an improved and leaner version of it require 'rubygems/util/licenses' # check for errors errors = [] # check for required keys %w[name version author license summary source dependencies].each do |key| errors.push("Required field '#{key}' not found.") unless parsed.key?(key) end # check requirements and dependencies keys %w[requirements dependencies].each do |key| # skip if key is missing or value is an empty string, array, or hash next if !parsed.key?(key) || parsed[key].empty? # check that dependencies and requirements are an array of hashes next errors.push("Field '#{key}' is not an array of hashes.") unless (parsed[key].is_a? Array) && (parsed[key][0].is_a? Hash) # check dependencies and requirements values names = [] parsed[key].each do |req_dep| # check for duplicate dependencies and requirements name = req_dep['name'] next errors.push("Duplicate #{key} on #{name}.") if names.include?(name) names << name # warn and skip if key is missing next warnings.push("'#{req_dep['name']}' is missing a 'version_requirement' key.") if req_dep['version_requirement'].nil? # warn and skip if no upper bound next warnings.push("'#{req_dep['name']}' is missing an upper bound.") unless req_dep['version_requirement'].include?('<') # check for semantic versioning if key == 'dependencies' warnings.push("'#{req_dep['name']}' has non-semantic versioning in its 'version_requirement' key.") unless req_dep['version_requirement'] =~ /\d+\.\d+\.\d+.*\d+\.\d+\.\d+/ end end end # check for deprecated fields %w[types checksum].each do |key| errors.push("Deprecated field '#{key}' found.") if parsed.key?(key) end # check for summary under 144 character errors.push('Summary exceeds 144 characters.') if parsed.key?('summary') && parsed['summary'].size > 144 next PuppetCheck.settings[:error_files].push("#{file}:\n#{errors.join("\n")}") unless errors.empty? # check for warnings # check for operatingsystem_support hash array if parsed.key?('operatingsystem_support') # check if operatingsystem_support array is actually empty if !(parsed['operatingsystem_support'].is_a? Array) || parsed['operatingsystem_support'].empty? || (!parsed['operatingsystem_support'].empty? && !(parsed['operatingsystem_support'][0].is_a? Hash)) warnings.push('Recommended field \'operatingsystem\' not found.') warnings.push('Recommended field \'operatingsystemrelease\' not found.') else # check for operatingsystem string if parsed['operatingsystem_support'][0].key?('operatingsystem') warnings.push('Field \'operatingsystem\' is not a string.') unless parsed['operatingsystem_support'][0]['operatingsystem'].is_a? String else warnings.push('Recommended field \'operatingsystem\' not found.') end # check for operatingsystemrelease string array if parsed['operatingsystem_support'][0].key?('operatingsystemrelease') warnings.push('Field \'operatingsystemrelease\' is not a string array.') unless parsed['operatingsystem_support'][0]['operatingsystemrelease'][0].is_a? String else warnings.push('Recommended field \'operatingsystemrelease\' not found.') end end else warnings.push('Recommended field \'operatingsystem_support\' not found.') end # check for spdx license if parsed.key?('license') && !Gem::Licenses.match?(parsed['license']) && parsed['license'] !~ /[pP]roprietary/ warnings.push("License identifier '#{parsed['license']}' is not in the SPDX list: http://spdx.org/licenses/") end # assume this is task metadata if it has this key elsif parsed.key?('description') # check that description is a string warnings.push('description value is not a String') unless parsed['description'].is_a?(String) # check that input_method is one of three possible values if parsed.key?('input_method') if parsed['input_method'].is_a?(String) warnings.push('input_method value is not one of environment, stdin, or powershell') unless %w[environment stdin powershell].include?(parsed['input_method']) else warnings.push('input_method value is not a String') end end # check that parameters is a hash if parsed.key?('parameters') warnings.push('parameters value is not a Hash') unless parsed['parameters'].is_a?(Hash) end # check that puppet_task_version is an integer if parsed.key?('puppet_task_version') warnings.push('puppet_task_version value is not an Integer') unless parsed['puppet_task_version'].is_a?(Integer) end # check that supports_noop is a boolean if parsed.key?('supports_noop') warnings.push('supports_noop value is not a Boolean') unless parsed['supports_noop'].is_a?(TrueClass) || parsed['supports_noop'].is_a?(FalseClass) end # assume this is hieradata and ensure it is non-empty elsif parsed # perform some rudimentary hiera checks if data exists warnings = hiera(parsed, file) end next PuppetCheck.settings[:warning_files].push("#{file}:\n#{warnings.join("\n")}") unless warnings.empty? PuppetCheck.settings[:clean_files].push(file.to_s) end end end |
.yaml(files) ⇒ Object
checks yaml (.yaml/.yml)
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# File 'lib/puppet-check/data_parser.rb', line 6 def self.yaml(files) require 'yaml' files.each do |file| # check yaml syntax begin parsed = YAML.load_file(file) rescue StandardError => err PuppetCheck.settings[:error_files].push("#{file}:\n#{err.to_s.gsub("(#{file}): ", '')}") else warnings = [] # perform some rudimentary hiera checks if data exists and is hieradata warnings = hiera(parsed, file) if parsed && (File.basename(file) != 'hiera.yaml') next PuppetCheck.settings[:warning_files].push("#{file}:\n#{warnings.join("\n")}") unless warnings.empty? PuppetCheck.settings[:clean_files].push(file.to_s) end end end |