REPOST of the old BigFix Relevance Musings Blog posting. The IBM Dev works copy is no longer active. This is the most popular entry, so I am parking a copy here until I have a new home for relevance blogging.
There are many ways to query computer properties in BigFix. Web Reports has the Explore page, console can show you properties for a computer, REST API can pull computer properties.
Sometimes you want an automated way to pull specific properties from a BigFix server serving a large number of total endpoints and you want to pull a few property values across all of the endpoints, and do it with automation/code. Session relevance will allow you to query “as needed” and pull properties.
(name of it, values of results (it, bes property "Computer Name"), values of results (it, bes property "IP Address") ) of bes computers
Simple and straight-forward. Take each computer, then get the values of the results from the property named “Computer Name” and "IP Address"for that specific computer.
- What could go wrong, you ask?
- More than one Property with that name.
- No properties with that name.
- Results plural will create one line per result. If all your property results are plural, you will get a cross product (mess)
- Missing results will drop that computer entry out of the tuple
- You create your property objects once for each computer. If you have 250,000 computers, that is a whole lot of creation of BES Property objects.
What can you do about it? Trap all of those possibilities and use Sets to conquer that subtle efficiency issue. I have been fooling around with this code structure for quite some time and I would like to share my current best of breed BigFix property query in session relevance
We start with a single, flattened tuple of sets. Notice that we only create each property object once and that I take care of case sensitivity. You can easily add more lines in for more properties. Note also that duplicate properties will be captured in those sets. We will catch that error later.
(
set of BES computers
, set of bes properties whose (name of it as lowercase = ("Computer Name") as lowercase)
, set of bes properties whose (name of it as lowercase = ("IP Address") as lowercase)
)
Next step is very simple. You expand the BES Computer set in item 0. This gets you each of your computers “on their own lines”. The other items, your property sets, you just pass through, untouched.
(
elements of item 0 of it /*expand the computer set into single computers*/
,item 1 of it
,item 2 of it
) of
final step is the part where all the error trapping will happen. First we will test our property sets to make sure they only have 1 property in them. If there are more than 1 or less than 1, we can then trap those errors separately.
if (size of item 1 of it = 1) then (/*good stuff*/) else (/*trap errors*/)
Let’s look at what will go into/*trap errors*/
. If we have more than one property, we output an error along with the names and IDs of the duplicated properties. If there are no properties in our set, we still have a set object (empty one) and we can report that the property does not exist.
if (size of item 2 of it > 1) then (("Property 2 duplicates: " & concatenation "|" of ((name of it) & "=" & (id of it as string)) of elements of item 2 of it) as string) else ("Property 2 does not exist")
Now let’s look at the /*good stuff*
/ branch of our if. If the property has no values, we catch the error and report it. If there are many values, we concatenate them into one line with a ; separator. I am not trapping for comma’s inside of the data, as the relevance engine will just parenthesize that case for me without extra code.
(if it = "" then "Property 2: No values" else it) of concatenation ";" of values of results (item 0 of it, elements of item 2 of it)
Those are the major features. Now let’s enjoy the the entire relevance statement assembled into one. You can easily add in additional tuple elements at each of the 3 layers if you want to add additional properties into this query. Note that missing properties or property results do not result in any dropped rows, and you exactly get one row per computer record, if it has results or not.
(
name of item 0 of it|"missing Name"
, (concatenation ";" of values of results (item 0 of it, elements of item 1 of it))
, (if (size of item 2 of it = 1) then ((if it = "" then "Property 2: No values" else it) of concatenation ";" of values of results (item 0 of it, elements of item 2 of it)) else (if (size of item 2 of it > 1) then (("Property 2 duplicates: " & concatenation "|" of ((name of it) & "=" & (id of it as string)) of elements of item 2 of it) as string) else ("Property 2 does not exist")))
, (if (size of item 3 of it = 1) then ((if it = "" then "Property 3: No values" else it) of concatenation ";" of values of results (item 0 of it, elements of item 3 of it)) else (if (size of item 3 of it > 1) then (("Property 3 duplicates: " & concatenation "|" of ((name of it) & "=" & (id of it as string)) of elements of item 3 of it) as string) else ("Property 3 does not exist")))
, (if (size of item 4 of it = 1) then ((if it = "" then "Property 4: No values" else it) of concatenation ";" of values of results (item 0 of it, elements of item 4 of it)) else (if (size of item 4 of it > 1) then (("Property 4 duplicates: " & concatenation "|" of ((name of it) & "=" & (id of it as string)) of elements of item 4 of it) as string) else ("Property 4 does not exist")))
, (if (size of item 5 of it = 1) then ((if it = "" then "Property 5: No values" else it) of concatenation ";" of values of results (item 0 of it, elements of item 5 of it)) else (if (size of item 5 of it > 1) then (("Property 5 duplicates: " & concatenation "|" of ((name of it) & "=" & (id of it as string)) of elements of item 5 of it) as string) else ("Property 5 does not exist")))
) of (
elements of item 0 of it /*expand the computer set - gets you one line per computer*/
,item 1 of it
,item 2 of it
,item 3 of it
,item 4 of it
,item 5 of it
) of (
set of BES computers
, set of bes properties whose (name of it as lowercase = ("BES Client Version") as lowercase) /*should usually exist and usually without duplicates */
, set of bes properties whose (name of it as lowercase = ("FooBar") as lowercase) /*probably does not exist, but does not cause any errors or ommissions*/
, set of bes properties whose (name of it as lowercase = ("operating system") as lowercase) /*usually multiple properties with this name - the output will report on this error and provide you property IDs*/
, set of bes properties whose (id of it = ((id of all bes sites whose (name of it = "ActionSite")), 4, 1)) /*example of hard coded property by ID in actionsite - this is Computer Name and it exists in all implementations*/
, set of bes properties whose ((id of it =(1, 204, 1))) /*site 1 is BES Support - can use this method to get properties as well - this is BES Client Version in BES Support site on all BigFix servers*/
)
I added the flattened relevance below for ease of cut and paste.
(name of item 0 of it|"missing Name" , (concatenation ";" of values of results (item 0 of it, elements of item 1 of it)) , (if (size of item 2 of it = 1) then ((if it = "" then "Property 2: No values" else it) of concatenation ";" of values of results (item 0 of it, elements of item 2 of it)) else (if (size of item 2 of it > 1) then (("Property 2 duplicates: " & concatenation "|" of ((name of it) & "=" & (id of it as string)) of elements of item 2 of it) as string) else ("Property 2 does not exist"))) , (if (size of item 3 of it = 1) then ((if it = "" then "Property 3: No values" else it) of concatenation ";" of values of results (item 0 of it, elements of item 3 of it)) else (if (size of item 3 of it > 1) then (("Property 3 duplicates: " & concatenation "|" of ((name of it) & "=" & (id of it as string)) of elements of item 3 of it) as string) else ("Property 3 does not exist"))) , (if (size of item 4 of it = 1) then ((if it = "" then "Property 4: No values" else it) of concatenation ";" of values of results (item 0 of it, elements of item 4 of it)) else (if (size of item 4 of it > 1) then (("Property 4 duplicates: " & concatenation "|" of ((name of it) & "=" & (id of it as string)) of elements of item 4 of it) as string) else ("Property 4 does not exist"))) , (if (size of item 5 of it = 1) then ((if it = "" then "Property 5: No values" else it) of concatenation ";" of values of results (item 0 of it, elements of item 5 of it)) else (if (size of item 5 of it > 1) then (("Property 5 duplicates: " & concatenation "|" of ((name of it) & "=" & (id of it as string)) of elements of item 5 of it) as string) else ("Property 5 does not exist")))) of (elements of item 0 of it /*expand the computer set - gets you one line per computer*/ ,item 1 of it ,item 2 of it ,item 3 of it ,item 4 of it ,item 5 of it) of (set of BES computers , set of bes properties whose (name of it as lowercase = ("BES Client Version") as lowercase) /*should usually exist and usually without duplicates */ , set of bes properties whose (name of it as lowercase = ("FooBar") as lowercase) /*probably does not exist, but does not cause any errors or ommissions*/ , set of bes properties whose (name of it as lowercase = ("operating system") as lowercase) /*usually multiple properties with this name - the output will report on this error and provide you property IDs*/ , set of bes properties whose (id of it = ((id of all bes sites whose (name of it = "ActionSite")) , 4, 1)) /*example of hard coded property by ID in actionsite - this is Computer Name and it exists in all implementations*/ , set of bes properties whose ((id of it =(1, 204, 1))) /*site 1 is BES Support - can use this method to get properties as well - this is BES Client Version in BES Support site on all BigFix servers*/)