Share:|

The listallthethings post you've all been waiting for right ?  This is the one I see come up most frequently on communities - I need to list out catalogs and all the stuff in them and do something to those objects or make some groups in the catalog.  The questions come up probably because there is not a released blcli namespace for Patch Smart Groups and no one is sure if a Catalog is a DepotObject or Group or turtle.  I mean it has a Job associated with it and Jobs are normally associated with DepotObjects.  But the Job is not in the Jobs workspace, it's in the catalog itself and a Catalog also has a bunch of DepotObjects and Groups in it.  So I'm going with turtle.

 

But a catalog is really a group.  If you want to be sure look for CATALOG and GROUP in the Object Type Ids list. Like RED_HAT_CATALOG_GROUP.  The requests I've seen are typically something like: find all my catalogs, find all the <os type> catalogs, find and run the CUJ, list the patch smart groups in a catalog, list the conditions of a patch smart group in a catalog, create a patch catalog smart group, list all the patches/errata/bulletins/etc in a catalog, set a property on the objects in the catalog if they meet some condition and delete all the stuff in my catalog.  So let's just dig right in.  Of course we have our trusty Unreleased blcli commands and documentation at the ready.

 

List all the catalogs of a specific OS type and do something to the CUJ

I'll combined these two asks together since it makes sense as you will see.  Since a catalog is a group, it made sense to me to start in the Group namespace.  I can lookup the object type id number or use a blcli command to convert the model type name to the number and then there's a command called Group.findAllByGroupType.  That looks like this:

blcli_execute Utility convertModelType RED_HAT_CATALOG_GROUP
blcli_storeenv groupType
blcli_execute Group findAllBytype ${groupType}

That gets me output like this:

[/Workspace/Patch Catalogs/RedHat Linux Patch Catalog, Id = 2001137;Name = RedHat Linux Patch Catalog;Desc = This is an example Patching Catalog for Redhat Linux Patching., /Workspace/Patch Catalogs/Test1, Id = 2210400;Name = Eagle;Desc = , /Workspace/Patch Catalogs/RedHat 6 and 7 x86_64, Id = 2208200;Name = RedHat 6 and 7 x86_64;Desc = , /Workspace/Patch Catalogs/RedHat 7 Newest, Id = 2208000;Name = RedHat 7 Newest;Desc = ]

That looks promising.  Group.findAllByGroupType says it outputs a list so I can then I could run a Utility.listPrint and then do some text processing on each line.  I'm a big fan of text processing but let's see what else we can do.  I tried to run some of the Group.get* commands on the list and they all threw errors.  Maybe I can iterate through the list like in the other examples.  That doesn't work so well because each item in the list is a different element of the catalog - one is the path, the other is the Id = xxx and so on.  Maybe there's a command in Group that will act on the list.  I'm back to text processing.  That's ok - I can just dump the list and look for the lines that have the Id = or the path.

 

That's not very elegant but it works.  I look around a little more in my Unreleased blcli commands and documentation and I find there's a PatchCatalog namespace.   And some os-specific namespaces like RedhatPatchCatalog are there and I don't see much in there that's useful for now.  PatchCatalog has a set of list*Catalogs commands that look good.  After a listPrint it looks good:

blcli_execute PatchCatalog listRedhatPatchCatalogs
blcli_execute Utility setTargetObject
blcli_execute Utility listPrint

/Workspace/Patch Catalogs/RedHat Linux Patch Catalog

/Workspace/Patch Catalogs/Test1

/Workspace/Patch Catalogs/RedHat 6 and 7 x86_64

/Workspace/Patch Catalogs/RedHat 7 Newest

Now I know the path to the group and the group type.  I can get the DBKey with PatchCatalog.getCatalogDBKeyByFullyQualifiedCatalogName or the id with PatchCatalog.getCatalogIdByFullyQualifiedCatalogName.  I can also get the Catalog Update Job DBKey with the PatchCatalog.getCUJDBKeyByFullyQualifiedCatalogName

blcli_execute Utility convertModelType RED_HAT_CATALOG_GROUP
blcli_storeenv groupType
blcli_execute PatchCatalog listRedhatPatchCatalogs
blcli_execute Utility setTargetObject
blcli_execute Utility listPrint
blcli_storelocal catalogs
while read catalog
     do
     blcli_execute PatchCatalog getCatalogDBKeyByFullyQualifiedCatalogName "${catalog}" ${groupType}
     blcli_storelocal catalogKey
     echo "DBKey: ${catalogKey}"
     blcli_execute PatchCatalog getCUJDBKeyByFullyQualifiedCatalogName REDHAT "${catalog}"
     blcli_storelocal cujKey
     echo "CUJKey: ${cujKey}"
done <<< "$(awk 'NF' <<< "${catalogs}")"

The while handles the spaces in the catalog paths (where a for would not).    There's some other commands that could do the same thing: PatchCatalog.getRedhatCatalogUpdateJobDBKey (and Windows, etc).  Often times that's the case.  Use whatever gets you the output you need.  There's no right answer.  If it works, it works.  Cool, now I can go off and run the CUJs, or update/remove/add a schedule and I have the Catalog key and path if I need that.  For example to feed into isCatalogLastUpdateSuccessful:

blcli_execute Utility convertModelType RED_HAT_CATALOG_GROUP
blcli_storeenv groupType
blcli_execute PatchCatalog listRedhatPatchCatalogs
blcli_execute Utility setTargetObject
blcli_execute Utility listPrint
blcli_storelocal catalogs
while read catalog
     do
     blcli_execute PatchCatalog getCatalogIdByFullyQualifiedCatalogName "${catalog}" ${groupType}
     blcli_storelocal catalogGroupId
     blcli_execute PatchCatalog isCatalogLastUpdateSuccessful ${catalogGroupId}
     blcli_storelocal isCatalogLastUpdateSuccessful
     echo "${catalog}:${isCatalogLastUpdateSuccessful}"
done  <<< "$(awk 'NF' <<< "${catalogs}")"

That's a quick and easy way to populate a dashboard or otherwise get a quick view of your catalog states.  If the run failed you could then get the CUJ Key, and dump the last job run log information and email it off. I know that's jumping from 0 to 60 wrt using the blcli but I learn by example so I'll teach by example.  Suffice to say at some point in my blcli usage I figured out how to do each of those things - find the latest run key, use that to get job run information, send an email - by poking around in the released/unreleased command docs, trying various commands in my test env and seeing what happened.  Here we go:

blcli_execute Utility convertModelType RED_HAT_CATALOG_GROUP
blcli_storeenv groupType
blcli_execute PatchCatalog listRedhatPatchCatalogs
blcli_execute Utility setTargetObject
blcli_execute Utility listPrint
blcli_storelocal catalogs

while read catalog
     do
     blcli_execute PatchCatalog getCatalogIdByFullyQualifiedCatalogName "${catalog}" ${groupType}
     blcli_storelocal catalogGroupId
     blcli_execute PatchCatalog isCatalogLastUpdateSuccessful ${catalogGroupId}
     blcli_storelocal isCatalogLastUpdateSuccessful
     if [[ "${isCatalogLastUpdateSuccessful}" = "true" ]]
        then
        blcli_execute PatchCatalog getCUJDBKeyByFullyQualifiedCatalogName REDHAT "${catalog}"
        blcli_storelocal cujKey
        # false is also returned if there are no runs
        blcli_execute JobRun findRunCountByJobKey ${cujKey}
        blcli_storelocal jobRunCount
        if [[ ${jobRunCount} -gt 0 ]]
                then
                blcli_execute JobRun findLastRunKeyByJobKeyIgnoreVersion ${cujKey}
                blcli_storelocal cujRunKey
                # get the start time of the cuj run and the job name for our log/email
                blcli_execute JobRun findByJobRunKey ${cujRunKey}
                blcli_execute JobRun getStartTime
                blcli_storelocal startTime
                blcli_execute JobRun getJobName
                blcli_storelocal jobName
                blcli_execute JobRun jobRunKeyToJobRunId ${cujRunKey}
                blcli_storelocal cujRunId
                blcli_execute JobRun getLogItemsByJobRunId ${cujRunId}
                blcli_storelocal cujLogItems
                echo "${cujLogItems}" > "/tmp/${catalog##*/}-${cujRunId}.log"
                blcli_execute Email sendMailWithAttachment appserver@example.com user@example.com "Log for failed CUJ: ${jobName} at: ${startTime}" "Please review attached log for errors" "/tmp" "${catalog##*/}-${cujRunId}.log"
        else
                echo "Catalog ${catalog} has had ${jobRunCount} runs..."
        fi
     fi
done  <<< "$(awk 'NF' <<< "${catalogs}")"

 

As a bonus, let's do all of that, but for all the catalog types.  And we'll use an associative array to help loop.  I'm just showing the looping logic and what needs to be parameterized, you can fill in the rest of the script.

typeset -A catalogTypeList
catalogTypeList=(listAixPatchCatalogs AIX_CATALOG_GROUP listDebianPatchCatalogs UBUNTU_CATALOG_GROUP listRedhatPatchCatalogs RED_HAT_CATALOG_GROUP listSolarisPatchCatalogs SOLARIS_CATALOG_GROUP listWindowsPatchCatalogs WINDOWS_CATALOG_GROUP)
for key in ${(k)catalogTypeList}
        do
        cliCall="${key}"
        modelType="${catalogTypeList[${key}]}"
        blcli_execute Utility convertModelType ${modelType}
        blcli_storeenv groupType
        blcli_execute PatchCatalog ${cliCall}
       [ ...... Rest of script above .....]       
 done 

 

 

That was more than I expected to cover.  The reset of the cases will move to subsequent posts.