elasticsearch_check.rb 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. # frozen_string_literal: true
  2. class Admin::SystemCheck::ElasticsearchCheck < Admin::SystemCheck::BaseCheck
  3. INDEXES = [
  4. InstancesIndex,
  5. AccountsIndex,
  6. TagsIndex,
  7. StatusesIndex,
  8. PublicStatusesIndex,
  9. ].freeze
  10. def skip?
  11. !current_user.can?(:view_devops)
  12. end
  13. def pass?
  14. return true unless Chewy.enabled?
  15. running_version.present? && compatible_version? && cluster_health['status'] == 'green' && indexes_match? && preset_matches?
  16. rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
  17. false
  18. end
  19. def message
  20. if running_version.blank?
  21. Admin::SystemCheck::Message.new(:elasticsearch_running_check)
  22. elsif !compatible_version?
  23. Admin::SystemCheck::Message.new(
  24. :elasticsearch_version_check,
  25. I18n.t(
  26. 'admin.system_checks.elasticsearch_version_check.version_comparison',
  27. running_version: running_version,
  28. required_version: required_version
  29. )
  30. )
  31. elsif !indexes_match?
  32. Admin::SystemCheck::Message.new(
  33. :elasticsearch_index_mismatch,
  34. mismatched_indexes.join(' ')
  35. )
  36. elsif cluster_health['status'] == 'red'
  37. Admin::SystemCheck::Message.new(:elasticsearch_health_red)
  38. elsif cluster_health['number_of_nodes'] < 2 && es_preset != 'single_node_cluster'
  39. Admin::SystemCheck::Message.new(:elasticsearch_preset_single_node, nil, 'https://docs.joinmastodon.org/admin/elasticsearch/#scaling')
  40. 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'
  41. Admin::SystemCheck::Message.new(:elasticsearch_reset_chewy)
  42. elsif cluster_health['status'] == 'yellow'
  43. Admin::SystemCheck::Message.new(:elasticsearch_health_yellow)
  44. else
  45. Admin::SystemCheck::Message.new(:elasticsearch_preset, nil, 'https://docs.joinmastodon.org/admin/elasticsearch/#scaling')
  46. end
  47. rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
  48. Admin::SystemCheck::Message.new(:elasticsearch_running_check)
  49. end
  50. private
  51. def cluster_health
  52. @cluster_health ||= Chewy.client.cluster.health
  53. end
  54. def running_version
  55. @running_version ||= begin
  56. Chewy.client.info['version']['number']
  57. rescue Faraday::ConnectionFailed, Elasticsearch::Transport::Transport::Error
  58. nil
  59. end
  60. end
  61. def compatible_wire_version
  62. Chewy.client.info['version']['minimum_wire_compatibility_version']
  63. end
  64. def required_version
  65. '7.x'
  66. end
  67. def compatible_version?
  68. running_version_ok? || compatible_wire_version_ok?
  69. rescue ArgumentError
  70. false
  71. end
  72. def running_version_ok?
  73. return false if running_version.blank?
  74. gem_version_running >= gem_version_required
  75. end
  76. def compatible_wire_version_ok?
  77. return false if compatible_wire_version.blank?
  78. gem_version_compatible_wire >= gem_version_required
  79. end
  80. def gem_version_running
  81. Gem::Version.new(running_version)
  82. end
  83. def gem_version_required
  84. Gem::Version.new(required_version)
  85. end
  86. def gem_version_compatible_wire
  87. Gem::Version.new(compatible_wire_version)
  88. end
  89. def mismatched_indexes
  90. @mismatched_indexes ||= INDEXES.filter_map do |klass|
  91. klass.base_name if Chewy.client.indices.get_mapping[klass.index_name]&.deep_symbolize_keys != klass.mappings_hash
  92. end
  93. end
  94. def indexes_match?
  95. mismatched_indexes.empty?
  96. end
  97. def es_preset
  98. ENV.fetch('ES_PRESET', 'single_node_cluster')
  99. end
  100. def preset_matches?
  101. case es_preset
  102. when 'single_node_cluster'
  103. cluster_health['number_of_nodes'] == 1
  104. else
  105. cluster_health['number_of_nodes'] > 1
  106. end
  107. end
  108. end