# frozen_string_literal: true class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck INDEXES = [ InstancesIndex, AccountsIndex, TagsIndex, StatusesIndex, PublicStatusesIndex, ].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/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/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.base_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