Class: Jamf::AdvancedSearch

Inherits:
APIObject show all
Includes:
Creatable, Criteriable, Sitable, Updatable
Defined in:
lib/jamf/api/classic/base_classes/advanced_search.rb

Overview

A Parent class for Advanced Computer, MobileDevice, and User searchs

Subclasses must define:

  • the constant RESULT_CLASS which is the JSS Module class of the item returned by the search, e.g. Jamf::Computer

  • the constant RESULT_ID_FIELDS, which is an Array of Symbols that come from the API in the search_results along with the symbolized display fields. E.g. for AdvancedComputerSearches, :id, :name, and :udid are present along with whatever display fields have been defined.

Constant Summary collapse

EXPORT_FORMATS =

Class Constants

i[csv tab xml].freeze
SITE_SUBSET =

Where is site data located in the API JSON?

:top

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(**args) ⇒ AdvancedSearch

Returns a new instance of AdvancedSearch.



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 127

def initialize(**args)
  super(**args)

  # @init_data now has the raw data
  # so fill in our attributes or set defaults

  @sql_text = @init_data[:sql_text]
  @site = Jamf::APIObject.get_name(@init_data[:site])

  @display_fields = @init_data[:display_fields] ? @init_data[:display_fields].map { |f| f[:name] } : []

  @search_results = @init_data[self.class::RESULT_CLASS::RSRC_LIST_KEY]
  @search_results ||= []
  @result_display_keys = if @search_results.empty?
                           []
                         else
                           @search_results[0].keys - self.class::RESULT_ID_FIELDS
                         end

  # make sure each hash of the search results
  # has a key matching a standard key.
  #
  # @search_results.each do |hash|
  #   hash.keys.each do |key|
  #     std_key = key.to_s.gsub(':', '').gsub(/ |-/, '_').to_sym
  #     next if hash[std_key]
  #     hash[std_key] = hash[key]
  #   end
  # end
end

Instance Attribute Details

#criteriaJamf::Criteriable::Criteria Originally defined in module Criteriable

#display_fieldsArray<String>

The API delivers these as an array of Hashes, where each hash has only one key, :name => the name of the fields/ExtAttrib to display. It should probably not have the underlying Hashes, and just be an array of names. This class converts it to just an Array of field names (Strings) for internal use.

These fields are returned in the @search_results data along with :id, :name, and other unique identifiers for each found item. In that data, their names have colons removed, abd spaces and dashes converted to underscores, and they are symbolized. See attribute result_display_keys



84
85
86
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 84

def display_fields
  @display_fields
end

#need_to_updateBoolean (readonly) Originally defined in module Updatable

#result_display_keysArray<Symbol> (readonly)

The search result Hash keys for the #display_fields of the search

The field names in #display_fields are strings matching how the field is labeled in the web UI (including the names of Extension Attributes). They have to be that way when submitting them to the API, and thats mostly what #display_fields and related methods are for.

However, when those names come back as the Hash Keys of the #search_results they (inconsistently) have spaces and/or dashes converted to underscores, and colons are removed. The JSON module then converts the keys to Symbols, so they don’t match the #display_fields.

For example, the display field “Last Check-in” might come back as any of these Symbols:

  • :“Last Check-in”

  • :Last_Check_in

  • :“Last_Check-in”

Also, the data returned in the #search_results contains more keys than just the #display_fields - namely it comes with some standard identifiers for each found item. such as JSS id number and name.

#result_display_keys will hold just the Hash keys corresponding to the #display_fields by taking the keys from the first result Hash, and removing the identifier keys as listed in each subclass’s RESULT_ID_FIELDS constant.



113
114
115
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 113

def result_display_keys
  @result_display_keys
end

#search_resultsArray<Hash> (readonly)

Each Hash is one object that matches the criteria. Within each hash there are variable keys, but always at least the keys defined in each subclasses RESULT_ID_FIELDS

The other keys correspond to the #display_fields defined for this Advanced Search.



68
69
70
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 68

def search_results
  @search_results
end

#siteString (readonly)



116
117
118
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 116

def site
  @site
end

#sql_textString (readonly)



119
120
121
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 119

def sql_text
  @sql_text
end

Instance Method Details

#clone(new_name, api: nil, cnx: nil) ⇒ APIObject Originally defined in module Creatable

make a clone of this API object, with a new name. The class must be creatable

#countInteger



249
250
251
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 249

def count
  @search_results.count
end

#create(get_results = false) ⇒ Integer

Create in the JSS

If get_results is true, they’ll be available in #search_results. This might be slow.



169
170
171
172
173
174
175
176
177
178
179
180
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 169

def create(get_results = false)
  raise Jamf::InvalidDataError, 'Jamf::Criteriable::Criteria instance required' unless @criteria.is_a? Jamf::Criteriable::Criteria
  raise Jamf::InvalidDataError, 'display_fields must be an Array.' unless @display_fields.is_a? Array

  orig_timeout = @cnx.timeout
  @cnx.timeout = 1800
  super()
  requery_search_results if get_results
  @cnx.timeout = orig_timeout

  @id # remember to return the id
end

#export(output_file, format = :csv, overwrite = false) ⇒ Pathname

Note:

This method only exports the display fields defined in this advanced search for

Export the display fields of the search results to a file.

the search_result members (computers, mobile_devices, or users) It doesn’t currently provide the ability to export subsets of info about those objects, as the Web UI does (e.g. group memberships, applications, receipts, etc)



268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 268

def export(output_file, format = :csv, overwrite = false)
  raise Jamf::InvalidDataError, "Export format must be one of: :#{EXPORT_FORMATS.join ', :'}" unless EXPORT_FORMATS.include? format

  out = Pathname.new output_file

  raise Jamf::AlreadyExistsError, "The output file already exists: #{out}" if !overwrite && out.exist?

  case format
  when :csv
    require 'csv'
    CSV.open(out.to_s, 'wb') do |csv|
      csv << @result_display_keys
      @search_results.each do |row|
        csv << @result_display_keys.map { |key| row[key] }
      end # each do row
    end # CSV.open

  when :tab
    tabbed = @result_display_keys.join("\t") + "\n"
    @search_results.each do |row|
      tabbed << @result_display_keys.map { |key| row[key] }.join("\t") + "\n"
    end # each do row
    out.jss_save tabbed.chomp

  else # :xml
    doc = REXML::Document.new Jamf::Connection::XML_HEADER
    doc.root.name = self.class::RESULT_CLASS::RSRC_LIST_KEY.to_s
    members = doc.root
    @search_results.each do |row|
      member = members.add_element self.class::RESULT_CLASS::RSRC_OBJECT_KEY.to_s
      @result_display_keys.each do |field|
        member.add_element(field.to_s.tr(' ', '_')).text = row[field].empty? ? nil : row[field]
      end # ech do field
    end # each do row
    out.jss_save doc.to_s.gsub('><', ">\n<")
  end # case

  out
end

#name=(newname) ⇒ void Originally defined in module Updatable

This method returns an undefined value.

Change the name of this item Remember to #update to push changes to the server.

#parse_criteriavoid Originally defined in module Criteriable

This method returns an undefined value.

During initialization, convert the @init_data Hash into a Jamf::Criteriable::Criteria instance stored in @criteria

Classes mixing in this module must call this in #initialize

#requery_search_resultsArray<Hash>

Requery the API for the search results.

This can be very slow, so temporarily reset the API timeout to 30 minutes



219
220
221
222
223
224
225
226
227
228
229
230
231
232
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 219

def requery_search_results
  orig_open_timeout = @cnx.open_timeout
  orig_timeout = @cnx.timeout
  @cnx.timeout = 1800
  @cnx.open_timeout = 1800
  begin
    requery = self.class.fetch(id: @id)
    @search_results = requery.search_results
    @result_display_keys = requery.result_display_keys
  ensure
    @cnx.timeout = orig_timeout
    @cnx.open_timeout = orig_open_timeout
  end
end

#save(get_results = false) ⇒ Object

Wrapper/alias for both create and update



201
202
203
204
205
206
207
208
209
210
211
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 201

def save(get_results = false)
  if @in_jss
    raise Jamf::UnsupportedError, 'Updating this object in the JSS is currently not supported by ruby-jss' unless updatable?

    update get_results
  else
    raise Jamf::UnsupportedError, 'Creating this object in the JSS is currently not supported by ruby-jss' unless creatable?

    create get_results
  end
end

#should_updatevoid Originally defined in module Criteriable

This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.

This method returns an undefined value.

Allow our Criteria to tell us when there’s been a change that needs to be updated.

#site=(new_site) ⇒ void Originally defined in module Sitable

This method returns an undefined value.

Change the site of this object. Any of the NON_SITES values will unset the site

#site_assigned?Boolean Originally defined in module Sitable

Does this object have a site assigned?

#site_idInteger Originally defined in module Sitable

The id of the site for this object.

#site_nameString Also known as: site Originally defined in module Sitable

The name of the site for this object. For backward compatibility, this is aliased to just ‘site’

#site_objectJamf::Site Originally defined in module Sitable

The Jamf::Site instance for this object’s site

#unset_sitevoid Originally defined in module Sitable

This method returns an undefined value.

Set the site to nothing

#update(get_results = false) ⇒ Integer

Save any changes

If get_results is true, they’ll be available in #search_results. This might be slow.



190
191
192
193
194
195
196
197
198
# File 'lib/jamf/api/classic/base_classes/advanced_search.rb', line 190

def update(get_results = false)
  orig_timeout = @cnx.timeout
  @cnx.timeout = 1800
  super()
  requery_search_results if get_results
  @cnx.timeout = orig_timeout

  @id # remember to return the id
end