# # Author:: Christine Draper () # Copyright:: Copyright (c) 2014 ThirdWave Insights LLC # License:: Apache License, Version 2.0 # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # require 'chef/knife/search' require 'chef/knife/topo/command_helper' module KnifeTopo # knife topo search class TopoSearch < Chef::Knife::Search deps do end banner 'knife topo search [ QUERY ] (options)' option( :topo, long: '--topo TOPOLOGY', description: 'Restrict search to nodes in the specified topology' ) option( :no_topo, long: '--no-topo', description: 'Restrict search to nodes that are not in any topology', boolean: true ) # Make the base search options available on topo search orig_opts = KnifeTopo::TopoSearch.options self.options = Chef::Knife::Search.options.merge(orig_opts) include KnifeTopo::CommandHelper def run setup_query super rescue StandardError => e raise if Chef::Config[:verbosity] == 2 ui.error "Topology search for \"#{@query}\" exited with error" humanize_exception(e) end def setup_query query_str = @name_args[0] || config[:query] topo_query = constrain_query(query_str, config[:topo]) # force a node search @name_args[0] = 'node' # override any query if config[:query] config[:query] = topo_query else @name_args[1] = topo_query end end def constrain_query(query, topo_name) # group existing query workaround for strange behavior with # NOTs and invalid query if put brackets round them group_query = query && !query.start_with?('NOT') ? "(#{query})" : query # search specific topologies or all/none constraint = topo_name ? 'topo_name:' + topo_name : 'topo_name:*' # combine the grouped query and constraint combine(query, group_query, constraint) end def combine(query, group_query, constraint) find_in_topo = config[:topo] || config[:no_topo].nil? if find_in_topo query ? "#{constraint} AND #{group_query}" : constraint else query ? "#{group_query} NOT #{constraint}" : "NOT #{constraint}" end end end end