class Oxidized::HTTP

Public Class Methods

new() click to toggle source
Calls superclass method Oxidized::Input::CLI::new
# File lib/oxidized/source/http.rb, line 3
def initialize
  @cfg = Oxidized.config.source.http
  super
end

Public Instance Methods

cmd(callback_or_string) click to toggle source
# File lib/oxidized/input/http.rb, line 32
def cmd(callback_or_string)
  return cmd_cb callback_or_string if callback_or_string.is_a?(Proc)

  cmd_str callback_or_string
end
cmd_cb(callback) click to toggle source
# File lib/oxidized/input/http.rb, line 38
def cmd_cb(callback)
  instance_exec(&callback)
end
cmd_str(string) click to toggle source
# File lib/oxidized/input/http.rb, line 42
def cmd_str(string)
  path = string % { password: @node.auth[:password] }
  get_http path
end
connect(node) click to toggle source
# File lib/oxidized/input/http.rb, line 9
def connect(node)
  @node = node
  @secure = false
  @username = nil
  @password = nil
  @headers = {}
  @log = File.open(Oxidized::Config::LOG + "/#{@node.ip}-http", "w") if Oxidized.config.input.debug?
  @node.model.cfg["http"].each { |cb| instance_exec(&cb) }

  return true unless @main_page && defined?(login)

  begin
    require "mechanize"
  rescue LoadError
    raise OxidizedError, "mechanize not found: sudo gem install mechanize"
  end

  @m = Mechanize.new
  url = URI::HTTP.build host: @node.ip, path: @main_page
  @m_page = @m.get(url.to_s)
  login
end
load(node_want = nil) click to toggle source
# File lib/oxidized/source/http.rb, line 20
def load(node_want = nil)
  nodes = []
  uri = URI.parse(@cfg.url)
  data = JSON.parse(read_http(uri, node_want))
  node_data = data
  node_data = string_navigate(data, @cfg.hosts_location) if @cfg.hosts_location?
  node_data = pagination(data, node_want) if @cfg.pagination?

  # at this point we have all the nodes; pagination or not
  node_data.each do |node|
    next if node.empty?

    # map node parameters
    keys = {}
    @cfg.map.each do |key, want_position|
      keys[key.to_sym] = node_var_interpolate string_navigate(node, want_position)
    end
    keys[:model] = map_model keys[:model] if keys.has_key? :model
    keys[:group] = map_group keys[:group] if keys.has_key? :group

    # map node specific vars
    vars = {}
    @cfg.vars_map.each do |key, want_position|
      vars[key.to_sym] = node_var_interpolate string_navigate(node, want_position)
    end
    keys[:vars] = vars unless vars.empty?

    nodes << keys
  end
  nodes
end
setup() click to toggle source
# File lib/oxidized/source/http.rb, line 8
def setup
  Oxidized.setup_logger
  return unless @cfg.url.empty?

  raise NoConfig, 'no source http url config, edit ~/.config/oxidized/config'
end

Private Instance Methods

basic_auth_header() click to toggle source
# File lib/oxidized/input/http.rb, line 84
def basic_auth_header
  "Basic " + ["#{@username}:#{@password}"].pack('m').delete("\r\n")
end
disconnect() click to toggle source
# File lib/oxidized/input/http.rb, line 92
def disconnect
  @log.close if Oxidized.config.input.debug?
end
get_http(path) click to toggle source
# File lib/oxidized/input/http.rb, line 49
def get_http(path)
  schema = @secure ? "https://" : "http://"
  uri = URI("#{schema}#{@node.ip}#{path}")

  Oxidized.logger.debug "Making request to: #{uri}"

  ssl_verify = Oxidized.config.input.http.ssl_verify? ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE

  res = make_request(uri, ssl_verify)

  if res.code == '401' && res['www-authenticate']&.include?('Digest')
    uri.user = @username
    uri.password = @password
    Oxidized.logger.debug "Server requires Digest authentication"
    auth = Net::HTTP::DigestAuth.new.auth_header(uri, res['www-authenticate'], 'GET')

    res = make_request(uri, ssl_verify, 'Authorization' => auth)
  elsif @username && @password
    Oxidized.logger.debug "Falling back to Basic authentication"
    res = make_request(uri, ssl_verify, 'Authorization' => basic_auth_header)
  end

  Oxidized.logger.debug "Response code: #{res.code}"
  res.body
end
log(str) click to toggle source
# File lib/oxidized/input/http.rb, line 88
def log(str)
  @log&.write(str)
end
make_request(uri, ssl_verify, extra_headers = {}) click to toggle source
# File lib/oxidized/input/http.rb, line 75
def make_request(uri, ssl_verify, extra_headers = {})
  Net::HTTP.start(uri.hostname, uri.port, use_ssl: uri.scheme == "https", verify_mode: ssl_verify) do |http|
    req = Net::HTTP::Get.new(uri)
    @headers.merge(extra_headers).each { |header, value| req.add_field(header, value) }
    Oxidized.logger.debug "Sending request with headers: #{@headers.merge(extra_headers)}"
    http.request(req)
  end
end
pagination(data, node_want) click to toggle source
# File lib/oxidized/source/http.rb, line 65
def pagination(data, node_want)
  node_data = []
  raise Oxidized::OxidizedError, "if using pagination, 'pagination_key_name' setting must be set" unless @cfg.pagination_key_name?

  next_key = @cfg.pagination_key_name
  loop do
    node_data += string_navigate(data, @cfg.hosts_location) if @cfg.hosts_location?
    break if data[next_key].nil?

    new_uri = URI.parse(data[next_key]) if data.has_key?(next_key)
    data = JSON.parse(read_http(new_uri, node_want))
    node_data += string_navigate(data, @cfg.hosts_location) if @cfg.hosts_location?
  end
  node_data
end
read_http(uri, node_want) click to toggle source
# File lib/oxidized/source/http.rb, line 81
def read_http(uri, node_want)
  http = Net::HTTP.new(uri.host, uri.port)
  http.use_ssl = true if uri.scheme == 'https'
  http.verify_mode = OpenSSL::SSL::VERIFY_NONE unless @cfg.secure

  # Add read_timeout to handle case of big list of nodes (default value is 60 seconds)
  http.read_timeout = Integer(@cfg.read_timeout) if @cfg.has_key? "read_timeout"

  # map headers
  headers = {}
  @cfg.headers.each do |header, value|
    headers[header] = value
  end

  req_uri = uri.request_uri
  req_uri = "#{req_uri}/#{node_want}" if node_want
  request = Net::HTTP::Get.new(req_uri, headers)
  request.basic_auth(@cfg.user, @cfg.pass) if @cfg.user? && @cfg.pass?
  http.request(request).body
end
string_navigate(object, wants) click to toggle source
# File lib/oxidized/source/http.rb, line 54
def string_navigate(object, wants)
  wants = wants.split(".").map do |want|
    head, match, _tail = want.partition(/\[\d+\]/)
    match.empty? ? head : [head, match[1..-2].to_i]
  end
  wants.flatten.each do |want|
    object = object[want] if object.respond_to? :each
  end
  object
end