~cytrogen/masto-fe

ref: 2f8f92df48326c7ae61679773e64afca46d9a374 masto-fe/app/lib/admin/system_check/elasticsearch_check.rb -rw-r--r-- 3.7 KiB
2f8f92df — Matt Jankowski Fix Elastic check deprecation warning about gem version (#27262) 2 years ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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
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
# 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?
    running_version_ok? || compatible_wire_version_ok?
  rescue ArgumentError
    false
  end

  def running_version_ok?
    return false if running_version.blank?

    gem_version_running >= gem_version_required
  end

  def compatible_wire_version_ok?
    return false if compatible_wire_version.blank?

    gem_version_compatible_wire >= gem_version_required
  end

  def gem_version_running
    Gem::Version.new(running_version)
  end

  def gem_version_required
    Gem::Version.new(required_version)
  end

  def gem_version_compatible_wire
    Gem::Version.new(compatible_wire_version)
  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