diff --git a/resources/scripts/rb_druid_supervisor_action.rb b/resources/scripts/rb_druid_supervisor_action.rb new file mode 100755 index 0000000..440cdec --- /dev/null +++ b/resources/scripts/rb_druid_supervisor_action.rb @@ -0,0 +1,113 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +####################################################################### +## Copyright (c) 2025 ENEO TecnologĂ­a S.L. +## This file is part of redBorder. +## redBorder is free software: you can redistribute it and/or modify +## it under the terms of the GNU Affero General Public License License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## redBorder is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Affero General Public License License for more details. +## You should have received a copy of the GNU Affero General Public License License +## along with redBorder. If not, see . +######################################################################## + +require 'zk' +require 'net/http' +require 'uri' +require 'json' +require 'optparse' + +def usage + puts 'rb_restart_druid_supervisor.rb [-h] -s ' + puts ' -h : show help' + puts ' -s : rb_monitor | rb_monitor_ | rb_vault | ...' + puts ' -a : shutdown | suspend | restart | resume' + puts 'To list active supervisors, run: rb_get_druid_supervisors' +end + +# ---------------------------------------------------------- +# Resolve a Druid Router host/port from ZooKeeper +# ---------------------------------------------------------- +def resolve_druid_router + begin + zk_hosts = 'zookeeper.service:2181' + zk = ZK.new(zk_hosts) + + druid_router_path = '/druid/discoveryPath/druid:router' + raise "Router path '#{druid_router_path}' does not exist in Zookeeper" unless zk.exists?(druid_router_path) + + routers = zk.children(druid_router_path) + raise 'ERROR: No routers found. Please enable druid router at least in one node.' if routers.empty? + + router_id = routers.sample + data, _stat = zk.get("#{druid_router_path}/#{router_id}") + + router_info = JSON.parse(data) || {} + raise 'ERROR on restart supervisor' unless router_info['address'] && router_info['port'] + + router_info + rescue => e + puts "ERROR on restart supervisor: #{e.message}" + exit 0 + ensure + zk&.close + end +end + +# ---------------------------------------------------------- +# Send action to supervisor via Druid Router +# ---------------------------------------------------------- +def post_to_supervisor(params) + address = params[:address] + port = params[:port] + supervisor_name = params[:supervisor_name] + action = params[:action] + + puts "Performing '#{action}' on supervisor '#{supervisor_name}' via #{address}:#{port}" + + # if action == 'delete' + # # DELETE /supervisor/{name} + # uri = URI("http://#{address}:#{port}/druid/indexer/v1/supervisor/#{supervisor_name}") + + # request = Net::HTTP::Delete.new(uri) + # else + uri = URI("http://#{address}:#{port}/druid/indexer/v1/supervisor/#{supervisor_name}/#{action}") + + request = Net::HTTP::Post.new(uri) + request['Content-Type'] = 'application/json' + request.body = { feed: supervisor_name }.to_json + # end + + response = Net::HTTP.start(uri.hostname, uri.port) { |http| http.request(request) } + + raise "HTTP #{response.code} #{response.message} - #{response.body}" unless response.is_a?(Net::HTTPSuccess) + + puts "Action '#{action}' completed successfully." +rescue => e + puts "ERROR performing '#{action}' on supervisor '#{supervisor_name}': #{e.message}" +end + +# ---------------------------------------------------------- +# MAIN +# ---------------------------------------------------------- +options = {} +OptionParser.new do |opts| + opts.on('-s VALUE', 'Supervisor name') { |v| options[:s] = v } + opts.on('-a VALUE', 'Supervisor action') { |v| options[:a] = v } + opts.on('-h', 'Help') { options[:h] = true } +end.parse! + +if options[:h] || options[:s].nil? || options[:a].nil? + usage + exit 0 +end + +router = resolve_druid_router + +params = { supervisor_name: options[:s], address: router['address'], port: router['port'], action: options[:a]} +post_to_supervisor(params) diff --git a/resources/scripts/rb_restart_druid_supervisor.rb b/resources/scripts/rb_restart_druid_supervisor.rb new file mode 100755 index 0000000..1da8d9d --- /dev/null +++ b/resources/scripts/rb_restart_druid_supervisor.rb @@ -0,0 +1,110 @@ +#!/usr/bin/env ruby +# frozen_string_literal: true + +####################################################################### +## Copyright (c) 2025 ENEO TecnologĂ­a S.L. +## This file is part of redBorder. +## redBorder is free software: you can redistribute it and/or modify +## it under the terms of the GNU Affero General Public License License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## redBorder is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Affero General Public License License for more details. +## You should have received a copy of the GNU Affero General Public License License +## along with redBorder. If not, see . +######################################################################## + +require 'zk' +require 'net/http' +require 'uri' +require 'json' +require 'optparse' + +def usage + puts 'rb_restart_druid_supervisor.rb [-h] -s ' + puts ' -h : show help' + puts ' -s : rb_monitor | rb_monitor_ | rb_vault | ...' + puts 'To list active supervisors, run: rb_get_druid_supervisors' +end + +# ---------------------------------------------------------- +# Resolve a Druid Router host/port from ZooKeeper +# ---------------------------------------------------------- +def resolve_druid_router + begin + zk_hosts = 'zookeeper.service:2181' + zk = ZK.new(zk_hosts) + + druid_router_path = '/druid/discoveryPath/druid:router' + raise "Router path '#{druid_router_path}' does not exist in Zookeeper" unless zk.exists?(druid_router_path) + + routers = zk.children(druid_router_path) + raise 'ERROR: No routers found. Please enable druid router at least in one node.' if routers.empty? + + # Pick one router randomly + router_id = routers.sample + data, _stat = zk.get("#{druid_router_path}/#{router_id}") + + router_info = JSON.parse(data) || {} + raise 'ERROR on restart supervisor' unless router_info['address'] && router_info['port'] + + router_info + rescue => e + puts "ERROR on restart supervisor: #{e.message}" + exit 0 + ensure + zk&.close + end +end + +# ---------------------------------------------------------- +# POST action to supervisor via Druid Router +# ---------------------------------------------------------- +def post_to_supervisor(params) + address = params[:address] + port = params[:port] + supervisor_name = params[:supervisor_name] + action = params[:action] + + puts "Performing '#{action}' on supervisor '#{supervisor_name}' via #{address}:#{port}" + + uri = URI("http://#{address}:#{port}/druid/indexer/v1/supervisor/#{supervisor_name}/#{action}") + + request = Net::HTTP::Post.new(uri) + request['Content-Type'] = 'application/json' + request.body = { feed: supervisor_name }.to_json + + response = Net::HTTP.start(uri.hostname, uri.port) { |http| http.request(request) } + + raise "HTTP #{response.code} #{response.message} - #{response.body}" unless response.is_a?(Net::HTTPSuccess) + + puts "Action '#{action}' completed successfully." +rescue => e + puts "ERROR performing '#{action}' on supervisor '#{supervisor_name}': #{e.message}" +end + +# ---------------------------------------------------------- +# MAIN +# ---------------------------------------------------------- +options = {} +OptionParser.new do |opts| + opts.on('-s VALUE', 'Supervisor name') { |v| options[:s] = v } + opts.on('-h', 'Help') { options[:h] = true } +end.parse! + +if options[:h] || options[:s].nil? + usage + exit 0 +end + +router = resolve_druid_router + +params = { supervisor_name: options[:s], address: router['address'], port: router['port'] } +params[:action] = 'suspend' +post_to_supervisor(params) +params[:action] = 'reset' +post_to_supervisor(params) +params[:action] = 'resume' +post_to_supervisor(params)