moduleForemanSalt# rubocop:disable ClassLengthclassReportImporterdelegate:logger,:to=>:Railsattr_reader:reportdefself.import(raw,proxy_id=nil)fail::Foreman::Exception.new(_('Invalid report'))unlessraw.is_a?(Hash)raw.mapdo|host,report|importer=ForemanSalt::ReportImporter.new(host,report,proxy_id)importer.importreport=importer.reportreport.origin='Salt'report.save!reportendenddefinitialize(host,raw,proxy_id=nil)@host=find_or_create_host(host)@raw=raw@proxy_id=proxy_idenddefimportlogger.info"processing report for #{@host}"logger.debug{"Report: #{@raw.inspect}"}if@host.new_record?&&!Setting[:create_new_host_when_report_is_uploaded]logger.info("skipping report for #{@host} as its an unknown host and create_new_host_when_report_is_uploaded setting is disabled")returnConfigReport.newend@host.salt_proxy_id||=@proxy_id@host.last_report=start_timeif@raw.is_a?Arrayprocess_failures# If Salt sends us only an array, it's a list of fatal failureselseprocess_normalend@host.save(:validate=>false)@host.reload@host.refresh_statuseslogger.info("Imported report for #{@host} in #{(Time.zone.now-start_time).round(2)} seconds")endprivatedeffind_or_create_host(host)@host||=Host::Managed.find_by_name(host)unless@hostnew=Host::Managed.new(:name=>host)new.save(:validate=>false)@host=newend@hostenddefimport_log_messages@raw.eachdo|resource,result|level=ifresult['changes'].blank?&&result['result']:infoelsifresult['result']==false:errelse# nil mean "unchanged" when running highstate with test=True:noticeendsource=Source.find_or_create(resource)message=ifresult['changes']['diff']result['changes']['diff']elsif!result['pchanges'].blank?&&result['pchanges'].include?('diff')result['pchanges']['diff']elsifresult['comment'].presenceresult['comment']else'No message available'endmessage=Message.find_or_create(message)Log.create(:message_id=>message.id,:source_id=>source.id,:report=>@report,:level=>level)endend# rubocop:disable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/AbcSize,Metrics/MethodLengthdefcalculate_metricssuccess=0failed=0changed=0restarted=0restarted_failed=0pending=0time={}@raw.eachdo|resource,result|nextunlessresult.is_a?Hashifresult['result']success+=1ifresource.match(/^service_/)&&result['comment'].include?('restarted')restarted+=1elsif!result['changes'].blank?changed+=1elsif!result['pchanges'].blank?pending+=1endelsifresult['result'].nil?pending+=1elsif!result['result']ifresource.match(/^service_/)&&result['comment'].include?('restarted')restarted_failed+=1elsefailed+=1endendduration=ifresult['duration'].is_a?StringFloat(result['duration'].delete(' ms'))rescuenilelseresult['duration']end# Convert duration from milliseconds to secondsduration/=1000ifduration.is_a?Floattime[resource]=duration||0endtime[:total]=time.values.compact.inject(&:+)||0events={:total=>changed+failed+restarted+restarted_failed,:success=>success+restarted,:failure=>failed+restarted_failed}changes={:total=>changed+restarted}resources={'total'=>@raw.size,'applied'=>changed,'restarted'=>restarted,'failed'=>failed,'failed_restarts'=>restarted_failed,'skipped'=>0,'scheduled'=>0,'pending'=>pending}{:events=>events,:resources=>resources,:changes=>changes,:time=>time}end# rubocop:enable Metrics/CyclomaticComplexity,Metrics/PerceivedComplexity,Metrics/AbcSize,Metrics/MethodLengthdefprocess_normalmetrics=calculate_metricsstatus=ConfigReportStatusCalculator.new(:counters=>metrics[:resources].slice(*::ConfigReport::METRIC)).calculate@report=ConfigReport.new(:host=>@host,:reported_at=>start_time,:status=>status,:metrics=>metrics)return@reportunless@report.saveimport_log_messagesenddefprocess_failuresstatus=ConfigReportStatusCalculator.new(:counters=>{'failed'=>@raw.size}).calculate@report=ConfigReport.create(:host=>@host,:reported_at=>Time.zone.now,:status=>status,:metrics=>{})source=Source.find_or_create('Salt')@raw.eachdo|failure|message=Message.find_or_create(failure)Log.create(:message_id=>message.id,:source_id=>source.id,:report=>@report,:level=>:err)endenddefstart_time@start_time||=Time.zone.nowendend# rubocop:enable ClassLengthend