Class: Hotdog::Commands::Search

Inherits:
BaseCommand show all
Defined in:
lib/hotdog/commands/search.rb

Direct Known Subclasses

SshAlike

Instance Attribute Summary collapse

Attributes inherited from BaseCommand

#application, #logger, #options, #persistent_db_path

Instance Method Summary collapse

Methods inherited from BaseCommand

#execute, #fixed_string?, #initialize, #reload, #use_fallback?

Constructor Details

This class inherits a constructor from Hotdog::Commands::BaseCommand

Instance Attribute Details

#remote_commandObject (readonly)

Returns the value of attribute remote_command.



33
34
35
# File 'lib/hotdog/commands/search.rb', line 33

def remote_command
  @remote_command
end

Instance Method Details

#define_options(optparse, options = {}) ⇒ Object



11
12
13
14
15
# File 'lib/hotdog/commands/search.rb', line 11

def define_options(optparse, options={})
  optparse.on("-n", "--limit LIMIT", "Limit result set to specified size at most", Integer) do |limit|
    options[:limit] = limit
  end
end

#evaluate(data, environment) ⇒ Object



95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/hotdog/commands/search.rb', line 95

def evaluate(data, environment)
  node = Hotdog::Expression::ExpressionTransformer.new.apply(data)
  if Hotdog::Expression::ExpressionNode === node
    optimized = node.optimize.tap do |optimized|
      logger.debug {
        JSON.pretty_generate(optimized.dump)
      }
    end
    result = optimized.evaluate(environment)
    if result.empty? and !$did_reload
      $did_reload = true
      environment.logger.info("reloading all hosts and tags.")
      environment.reload(force: true)
      optimized.evaluate(environment)
    else
      result
    end
  else
    raise("parser error: unknown expression: #{node.inspect}")
  end
end

#get_hosts_with_search_tags(result, node) ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
# File 'lib/hotdog/commands/search.rb', line 59

def get_hosts_with_search_tags(result, node)
  drilldown = ->(n) {
    case
    when n[:left] && n[:right] then drilldown.(n[:left]) + drilldown.(n[:right])
    when n[:expression] then drilldown.(n[:expression])
    when n[:tagname] then [n[:tagname]]
    else []
    end
  }
  if options[:display_search_tags]
    tagnames = drilldown.call(node).map(&:to_s)
    if options[:primary_tag]
      tags = [options[:primary_tag]] + tagnames
    else
      tags = tagnames
    end
  else
    tags = nil
  end
  get_hosts(result, tags)
end

#parse(expression) ⇒ Object



81
82
83
84
85
86
87
88
89
90
91
92
93
# File 'lib/hotdog/commands/search.rb', line 81

def parse(expression)
  logger.debug(expression)
  parser = Hotdog::Expression::ExpressionParser.new
  parser.parse(expression).tap do |parsed|
    logger.debug {
      begin
        JSON.pretty_generate(JSON.load(parsed.to_json))
      rescue JSON::NestingError => error
        error.message
      end
    }
  end
end

#parse_options(optparse, args = []) ⇒ Object



17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/hotdog/commands/search.rb', line 17

def parse_options(optparse, args=[])
  if args.index("--")
    command_args = args.slice(args.index("--") + 1, args.length)
    if command_args.length <= 1
      # Use given argument as is if the remote command is specified as a quoted string
      # e.g. 'for f in /tmp/foo*; do echo $f; done'
      @remote_command = command_args.first
    else
      @remote_command = Shellwords.shelljoin(command_args)
    end
    optparse.parse(args.slice(0, args.index("--")))
  else
    @remote_command = nil
    optparse.parse(args)
  end
end

#run(args = [], options = {}) ⇒ Object



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
# File 'lib/hotdog/commands/search.rb', line 35

def run(args=[], options={})
  if @remote_command
    logger.warn("ignore remote command: #{@remote_command}")
  end
  expression = rewrite_expression(args.join(" ").strip)

  begin
    node = parse(expression)
  rescue Parslet::ParseFailed => error
    STDERR.puts("syntax error: " + error.cause.ascii_tree)
    exit(1)
  end

  result0 = evaluate(node, self)
  if 0 < result0.length
    result, fields = get_hosts_with_search_tags(result0, node)
    STDOUT.print(format(result, fields: fields))
    logger.info("found %d host(s)." % result.length)
  else
    logger.error("no match found: #{expression}")
    exit(1)
  end
end