108 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
			
		
		
	
	
			108 lines
		
	
	
	
		
			3.3 KiB
		
	
	
	
		
			Ruby
		
	
	
	
	
	
# frozen_string_literal: true
 | 
						|
 | 
						|
class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
 | 
						|
  INDEXES = [
 | 
						|
    InstancesIndex,
 | 
						|
    AccountsIndex,
 | 
						|
    TagsIndex,
 | 
						|
    StatusesIndex,
 | 
						|
  ].freeze
 | 
						|
 | 
						|
  def skip?
 | 
						|
    !current_user.can?(:view_devops)
 | 
						|
  end
 | 
						|
 | 
						|
  def pass?
 | 
						|
    return true unless Chewy.enabled?
 | 
						|
 | 
						|
    running_version.present? && compatible_version? && cluster_health['status'] == 'green' && indexes_match? && preset_matches?
 | 
						|
  rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
 | 
						|
    false
 | 
						|
  end
 | 
						|
 | 
						|
  def message
 | 
						|
    if running_version.blank?
 | 
						|
      Admin::SystemCheck::Message.new(:elasticsearch_running_check)
 | 
						|
    elsif !compatible_version?
 | 
						|
      Admin::SystemCheck::Message.new(
 | 
						|
        :elasticsearch_version_check,
 | 
						|
        I18n.t(
 | 
						|
          'admin.system_checks.elasticsearch_version_check.version_comparison',
 | 
						|
          running_version: running_version,
 | 
						|
          required_version: required_version
 | 
						|
        )
 | 
						|
      )
 | 
						|
    elsif !indexes_match?
 | 
						|
      Admin::SystemCheck::Message.new(
 | 
						|
        :elasticsearch_index_mismatch,
 | 
						|
        mismatched_indexes.join(' ')
 | 
						|
      )
 | 
						|
    elsif cluster_health['status'] == 'red'
 | 
						|
      Admin::SystemCheck::Message.new(:elasticsearch_health_red)
 | 
						|
    elsif cluster_health['number_of_nodes'] < 2 && es_preset != 'single_node_cluster'
 | 
						|
      Admin::SystemCheck::Message.new(:elasticsearch_preset_single_node, nil, 'https://docs.joinmastodon.org/admin/optional/elasticsearch/#scaling')
 | 
						|
    elsif Chewy.client.indices.get_settings[Chewy::Stash::Specification.index_name]&.dig('settings', 'index', 'number_of_replicas')&.to_i&.positive? && es_preset == 'single_node_cluster'
 | 
						|
      Admin::SystemCheck::Message.new(:elasticsearch_reset_chewy)
 | 
						|
    elsif cluster_health['status'] == 'yellow'
 | 
						|
      Admin::SystemCheck::Message.new(:elasticsearch_health_yellow)
 | 
						|
    else
 | 
						|
      Admin::SystemCheck::Message.new(:elasticsearch_preset, nil, 'https://docs.joinmastodon.org/admin/optional/elasticsearch/#scaling')
 | 
						|
    end
 | 
						|
  rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
 | 
						|
    Admin::SystemCheck::Message.new(:elasticsearch_running_check)
 | 
						|
  end
 | 
						|
 | 
						|
  private
 | 
						|
 | 
						|
  def cluster_health
 | 
						|
    @cluster_health ||= Chewy.client.cluster.health
 | 
						|
  end
 | 
						|
 | 
						|
  def running_version
 | 
						|
    @running_version ||= begin
 | 
						|
      Chewy.client.info['version']['number']
 | 
						|
    rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
 | 
						|
      nil
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def compatible_wire_version
 | 
						|
    Chewy.client.info['version']['minimum_wire_compatibility_version']
 | 
						|
  end
 | 
						|
 | 
						|
  def required_version
 | 
						|
    '7.x'
 | 
						|
  end
 | 
						|
 | 
						|
  def compatible_version?
 | 
						|
    return false if running_version.nil?
 | 
						|
 | 
						|
    Gem::Version.new(running_version) >= Gem::Version.new(required_version) ||
 | 
						|
      Gem::Version.new(compatible_wire_version) >= Gem::Version.new(required_version)
 | 
						|
  rescue ArgumentError
 | 
						|
    false
 | 
						|
  end
 | 
						|
 | 
						|
  def mismatched_indexes
 | 
						|
    @mismatched_indexes ||= INDEXES.filter_map do |klass|
 | 
						|
      klass.index_name if Chewy.client.indices.get_mapping[klass.index_name]&.deep_symbolize_keys != klass.mappings_hash
 | 
						|
    end
 | 
						|
  end
 | 
						|
 | 
						|
  def indexes_match?
 | 
						|
    mismatched_indexes.empty?
 | 
						|
  end
 | 
						|
 | 
						|
  def es_preset
 | 
						|
    ENV.fetch('ES_PRESET', 'single_node_cluster')
 | 
						|
  end
 | 
						|
 | 
						|
  def preset_matches?
 | 
						|
    case es_preset
 | 
						|
    when 'single_node_cluster'
 | 
						|
      cluster_health['number_of_nodes'] == 1
 | 
						|
    else
 | 
						|
      cluster_health['number_of_nodes'] > 1
 | 
						|
    end
 | 
						|
  end
 | 
						|
end
 |