foigus' Notes

Mostly OS X Admin Related

Tag Archives: munki

More Thoughts on Munki’s AutoRemove

Previously I had discussed using autoremove for Adobe CC 2014 Installer Items, believing the best option to conserve disk space was to automatically remove Adobe CC since “Hey, if I didn’t put it there, it’s not needed.”  A couple of recent experiences has changed my mind.

  • I recently installed the Adobe CC 2014 suite on a computer where some Adobe CC 2014 applications were already installed.  While the client’s manifest was set up properly, I use the “site_default” manifest as a starting point to configure a handful of settings.  Unfortunately I chose to include the “production” catalog in the “site_default” manifest.  Since “site_default” (naturally) doesn’t include any Adobe CC 2014 products, Munki checked software for removal and attempted to remove the Adobe CC 2014 software it discovered.  In order to prevent future unintended actions, I created a separate “site-default-catalog” catalog for the “site_default” manifest, thus lowering the chance I shoot myself in the foot.*
  • Both the “old” CS6 suite and the “new” Adobe CC 2014 suite include the now-discontinued Fireworks CS6. I had both Fireworks CS6 packaged by AAMEE (licensed via ETLA) and Fireworks CS6 packaged by CCP (licensed via Creative Cloud) available in my Munki repo as unique Installer Items. I then installed Fireworks CS6 from the AAMEE-based Installer Item.  On the next managedsoftwareupdate run Munki noticed Fireworks CS6 was installed and the Fireworks CS6 Installer Item from the CCP-based installer was not included in the client’s manifest and therefore should be removed. Thus Munki had it’s own titanic battle with itself, alternately uninstalling and reinstalling Fireworks CS6 with each subsequent managedsoftwareupdate run.

*Note I didn’t say Munki succeeded in uninstalling the CC 2014 software.  Since I was still testing Munki 2.1’s support of CCP pkgs, I hadn’t yet made Munki 2.1 available in the “production” catalog.  Thus the CCP Installer Item’s uninstall_method of “AdobeCCPUninstaller” wasn’t understood by the older Munki client and uninstall failed.

Due to the two items above I’ve decided that setting “autoremove” to true for Adobe CC 2014 isn’t the best choice.  I’ve pared back my “autoremove” to the serialization Installer Items rather than the Adobe CC 2014 Installer Items themselves.

Advertisements

Distributing DPS Desktop Tools for InDesign CC 2014 with Munki

Adobe’s Digital Publishing Suite (DPS) is a group of add-on tools and services that facilitates tablet publications.  Let’s examine distributing the desktop software portion of these tools, “DPS Desktop Tools for InDesign CC 2014”, with Munki.

Red Herrings
It turns out DPS Desktop Tools for InDesign CC 2014 (hereafter referred to as DPS Desktop Tools) is surprisingly difficult to deploy.  Reviewing over the options:

  • Repackaging is generally considered harmful.  Attempting to collect the products of an installation and reproduce the intention of the original installer is difficult.  Although my organization is repackaging DPS Desktop Tools for InDesign CS6 (and I know others are as well) I wanted to avoid this if possible with DPS Desktop Tools for InDesign CC 2014.
  • Creative Cloud Packager (CCP) (and its predecessor, Adobe Application Manager Enterprise Edition (AAMEE)) intentionally block DPS Desktop Tools updates.  This is because DPS Desktop Tools’ “inclusion [in a CCP package] results in a much higher rate of failure of the deployment package“.  Sometimes DPS Desktop Tools accidentally sneaks into a CCP package, but the results are failure-prone.
  • Command-line (CLI) installation per the Adobe support article for installing DPS Desktop Tools mentions “Enter[ing] administrator credentials when prompted”, which means a non-administrator can’t install the software.  Also, per the support article CLI installation requires “…that client or user is logged in..”, complicating distribution.
  • CLI installation with administrative rights isn’t mentioned in the Adobe support article for installing DPS Desktop Tools.  It turns out this isn’t because it was forgotten–instead CLI installation with administrative rights (e.g. “sudo”) leads to no authentication prompt, but also leads to a near-guaranteed installation hang.  Earlier versions of the Adobe support article for DPS Desktop Tools mentioned “sudo”, implying there was more flexibility during installation, but this appears to either be in error or installation with “sudo” stopped working at some point.
  • CLI installation with the bsexec hack, used when a command needs to run in a different context than the current context, is a possible option.  Munki uses it to install some Adobe software, but my testing results appeared to show that installation via the bsexec hack fails regardless of whether a user is logged in or not.

Given all the above, deployment of DPS Desktop Tools appears to be a dead subject.  Repackaging must be the only way…

Accidental Installation
…Luckily, no one had written up the above information when I examined deploying DPS Desktop Tools via Munki.  I downloaded the installer, munkiimported it, and it worked.  Like my CC 2014 CCP pkgs, I set the RestartAction for the DPS Desktop Tools installer pkginfo to “RequireLogout”, so these installations took place at the Login Window.

However when I compared notes with other colleagues, those who had attempted to install DPS Desktop Tools had varied levels of success.  Usually the result of DPS Desktop Tools installation was a collegiate computer lab worth of failed installations and hung computers.  Further testing led me to discover that DPS Desktop Tools worked at the Login Window if run by Munki automatically, but not when installed by running “managedsoftwareupdate –installonly” or “managedsoftwareupdate –auto” via SSH.

Not wishing to spend large amounts of time tracking down random installation failures, I engaged Adobe support to help determine a reproducible way to install DPS Desktop Tools.  Through some gracious help examining why Munki inadvertently works (sometimes), it was determined that if the following conditions were met that DPS Desktop Tools could be reliably installed:

  • A user was logged into OS X during the installation (following the requirements of the support article)
  • A LaunchDaemon performed the installation (mimicking Munki’s use of a LaunchDaemon handling installation duties)

Adobe support provided with an unsupported installation method that installed a LaunchDaemon and used it to install DPS Desktop Tools.

Setting up Installation via Munki
The first step is to give Munki the ability to determine whether a user is logged in.  This is necessary since Munki normally attempts to install software when the computer is at the Login Window, but I’m specifically trying to prevent this behavior.  My solution was to write an Admin Provided Condition that checked to see if a user was logged in (further information regarding writing an Admin Provided Condition is available at Tim Sutton’s blog, in the article “Keeping your OS X VM guest tools current with Munki” under the heading “Writing an admin-provided condition”).  Leaning on a suggestion from Michael Lynn in ##osx-server IRC regarding the most appropriate way to determine if a user is logged in, I created this Admin Provided Condition:

#!/bin/bash

plistLocation=/Library/Managed\ Installs/ConditionalItems

#Verify a user is logged in
loggedInUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");'`

if [ ! -z "${loggedInUser}" ]
then
  defaults write "${plistLocation}" isUserLoggedIn -bool true
else
  defaults write "${plistLocation}" isUserLoggedIn -bool false
fi

This script needs to be installed here (note only the directory is important–the script name itself could be anything):

/usr/local/munki/conditions/isUserLoggedInCondition.sh

Each time managedsoftwareupdate runs, the above script will be executed and the result of testing whether or not a user is logged in will be available for evaluation as a Conditional Item.  Thus adding an installable_condition such as the following to a Munki Installer Item’s pkginfo will detect whether a user is logged in*:

<key>installable_condition</key>
<string>isUserLoggedIn == TRUE</string>

Being Extra, Extra, Extra Sure a User is Logged In
*But will the installable_condition guarantee a user is logged in during installation?  Certainly the installable_condition works to prevent installation attempts when no one is logged in, but Managed Software Center collects all pending Installer Items and installs them together.  If one Installer Item requires a logout or a restart (i.e. its pkginfo declares a “RestartAction” of “RequireLogout”, “RequireRestart”, or “RequireShutdown”), Managed Software Center will log the user out and perform all installations at the Login Window.  This will make the DPS Desktop Tools installation fail, so additional checks are necessary to ensure a user is still logged in when DPS Desktop Tools installation occurs.  I added these additional checks in three places: the preinstall_script in the DPS Desktop Tools pkginfo and the preflight and postflight scripts for the DPS Desktop Tools pkg itself.  For the preinstall_script and the DPS Desktop Tools package preflight script:

#!/bin/bash

#If a user isn't logged in, fail
loggedInUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");'`

if [ -z "${loggedInUser}" ]
then
  exit 1
fi

exit 0

The postflight script will be covered below.

Package Work
The structure of the DPS Desktop Tools installation package is the following:

  • Preflight
    • Verifies a user is logged in
  • Payloads
    • DPS Desktop Tools dmg
      /Users/Shared/AdobeDigitalPublishingPatch-CC2014-32.0.0.dmg
    • LaunchD job
      /Users/Shared/com.organization.dpsinstaller.plist
    • LaunchD-run installation script
      /Users/Shared/installDPS.sh
  • Postflight
    • Verifies a user is logged in
    • Loads LaunchD job and waits for the job to exit
      • LaunchD job runs DPS installation script
        • Mounts dmg
        • Installs DPS
        • Unmounts dmg
        • Unloads LaunchD job via launchctl unload
    • Deletes LaunchD-run installation script
    • Deletes LaunchD job file
    • Deletes DPS Desktop Tools dmg

The pieces of this installation:

  • Preflight (same as noted earlier, but here it is again)
    #!/bin/bash
    
    #If a user isn't logged in, fail
    loggedInUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");'`
    
    if [ -z "${loggedInUser}" ]
    then
      exit 1
    fi
    
    exit 0
  • DPS Desktop Tools installer dmg
  • LaunchD job
    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
      <key>Label</key>
      <string>com.organization.dpsinstaller</string>
      <key>ProgramArguments</key>
      <array>
        <string>/Users/Shared/installDPS.sh</string>
      </array>
      <key>RunAtLoad</key>
      <true/>
    </dict>
    </plist>
  • Installation script run by LaunchD job
    #!/bin/bash
    
    pathToDmg=/Users/Shared/AdobeDigitalPublishingPatch-CC2014-32.0.0.dmg
    volumeName=AdobeDigitalPublishingCC2014-AdobeUpdate
    pathToAdobePatchInstaller=/AdobeDigitalPublishingCC2014-AdobeUpdate/AdobePatchInstaller.app/Contents/MacOS/AdobePatchInstaller
    pathToLaunchDJob=/Users/Shared/com.organization.dpsinstaller.plist
    
    #Mount the dmg
    /usr/bin/hdiutil attach "${pathToDmg}" -nobrowse
    
    #Install the update
    #It would be great to collect the exit status, but AdobePatchInstaller appears
    #to always exit 0
    /Volumes/"${volumeName}${pathToAdobePatchInstaller}" --mode=silent --skipProcessCheck=1
    
    #Eject the dmg
    /usr/bin/hdiutil detach /Volumes/"${volumeName}"
    
    #Unload the LaunchDaemon
    /bin/launchctl unload "${pathToLaunchDJob}"
  • Postflight (Note that since the postflight script runs after the package payloads have been installed, the postflight script goes through extra cleanup steps to remove those payloads if the check for a logged-in user fails)
    #!/bin/bash
    
    #Paths to important files
    pathToDPSInstallScript=/Users/Shared/installDPS.sh
    pathToLaunchDJob=/Users/Shared/com.organization.dpsinstaller.plist
    pathToDmg=/Users/Shared/AdobeDigitalPublishingPatch-CC2014-32.0.0.dmg
    
    loggedInUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");'`
    
    #If a user isn't logged in, delete the payloads of the pkg and fail
    if [ -z "${loggedInUser}" ]
    then
      /bin/rm "${pathToDPSInstallScript}"
      /bin/rm "${pathToLaunchDJob}"
      /bin/rm "${pathToDmg}"
      exit 1
    fi
    
    #Determine the name of the LaunchD job
    launchDJobName=`/usr/bin/basename "${pathToLaunchDJob}" .plist`
    
    #Load the LaunchDaemon
    /bin/launchctl load "${pathToLaunchDJob}"
    
    #Wait for the LaunchDaemon to exit
    sleep 5
    while /bin/launchctl list | /usr/bin/grep -wq "${launchDJobName}"
    do
      sleep 5
    done
    
    #Delete the payloads of the pkg
    /bin/rm "${pathToDPSInstallScript}"
    /bin/rm "${pathToLaunchDJob}"
    /bin/rm "${pathToDmg}"
    
    #Exit cleanly. How else can we exit? The DPS installer does not exit with a status
    exit 0

Uninstallation
As discussed in my Distributing Adobe CC 2014 via Munki post, I’d like uninstallers for my Adobe CC 2014 applications.  In my testing, DPS Desktop Tools installs one InDesign plugin (/Applications/Adobe InDesign CC 2014/Plug-Ins/Graphics/Digital Publishing.InDesignPlugin) and two applications (/Applications/DPS App Builder.app and /Applications/Adobe/Adobe Content Viewer.app).  My testing also revealed that uninstalling InDesign CC 2014 removes the plugin, but leaves the applications installed.  Assuming I’m never going to remove the DPS Desktop Tools without also subsequently removing InDesign, a postuninstall_script of the following is sufficient:

#!/bin/bash

#Delete DPS App Builder and Adobe Content Viewer
/bin/rm -rf /Applications/DPS\ App\ Builder.app
/bin/rm -rf /Applications/Adobe/Adobe\ Content\ Viewer.app

exit 0

If removal of just DPS Desktop Tools is desired, it may be possible to add /Applications/Adobe InDesign CC 2014/Plug-Ins/Graphics/Digital Publishing.InDesignPlugin to the above list of files to delete, however this is untested so your mileage may vary.

Miscellaneous Topics
Applicability to other versions of DPS Desktop Tools
All of the testing here has been specific to the InDesign CC 2014 version of DPS Desktop Tools.  It’s unknown whether other versions of DPS Desktop Tools for InDesign CC or InDesign CS6 will encounter the same issues or if the same techniques will solve those issues.

DPS Desktop Tools as an optional_install
It may be tempting to add DPS Desktop Tools as an optional_install and forgo the preceding steps forcing installation only when a user is logged in.  However remember that once a user adds an optional_install, that updated versions of the Installer Item may be installed at any time the pkginfo allows.  So even if DPS Desktop Tools is just an optional_install, remember to follow the rest of the steps to prevent installation when a user isn’t logged in.

blocking_applications
The DPS Desktop Installer offers a list of blocking applications inside the mounted installer dmg:

/Volumes/AdobeDigitalPublishingCC2014-AdobeUpdate/AdobeDigitalPublishingCC2014-AdobeUpdate/payloads/UpdateManifest.xml

in the ConflictingProcesses section.  This list includes the following applications:

  • Adobe Content Viewer*
  • Adobe InDesign CS*
  • Creative Cloud Connection*
  • DPS App Builder*
  • InDesign CS*
  • InDesign*
  • Viewer Builder*

The asterisks (which are presumably wildcards) are part of the original list, implying that different software versions such as InDesign CS4 or InDesign CS5 could potentially interfere with a DPS Desktop Tools installation.  Also note that Munki’s blocking_applications currently does not support wildcards to match running applications.  It’s up to you to create a list of blocking_applications appropriate for your environment.

autoremove
In the spirit of my earlier post about Distributing Adobe CC 2014 via Munki, I set AutoRemove to “true” in the DPS Desktop Tools pkginfo.

installs Array
To help Munki intelligently examine the current installation of DPS Desktop Tools, an installs array is necessary.  This command when run against a computer with DPS Desktop Tools installed will generate an installs array for the three items installed:

makepkginfo -f /Applications/DPS App Builder.app -f /Applications/Adobe/Adobe Content Viewer.app -f /Applications/Adobe InDesign CC 2014/Plug-Ins/Graphics/Digital Publishing.InDesignPlugin

Copy the installs array and paste it into the pkginfo for DPS Desktop Tools.

update_for
If it’s desired to automatically install DPS Desktop Tools following every InDesign CC 2014 installation, make DPS Desktop Tools an update_for InDesign CC 2014.

requires
Since we’ve made DPS Desktop Tools dependent on an Admin Provided Condition, let’s require that Admin Provided condition.  I added the Installer Item “IsUserLoggedInCondition” to the “requires” array in the pkginfo for DPS Desktop Tools.

unattended_install
In order to get the best chance DPS Desktop Tools will be installed (since I’d prefer not to ask the user’s permission unless a blocking_application is running), I set unattended_install to true in the pkginfo for DPS Desktop Tools.

Example pkginfo
For review, here’s the entire pkginfo for the DPS Desktop Tools package created above:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>_metadata</key>
  <dict>
    <key>created_by</key>
    <string>admin</string>
    <key>creation_date</key>
    <date>2014-11-03T21:04:48Z</date>
    <key>munki_version</key>
    <string>2.0.0.2212</string>
    <key>os_version</key>
    <string>10.9.5</string>
  </dict>
  <key>autoremove</key>
  <true/>
  <key>catalogs</key>
  <array>
    <string>production</string>
  </array>
  <key>category</key>
  <string>Productivity</string>
  <key>description</key>
  <string>Digital publishing tools for InDesign CC 2014</string>
  <key>developer</key>
  <string>Adobe</string>
  <key>display_name</key>
  <string>DPS Desktop Tools CC2014</string>
  <key>installed_size</key>
  <integer>77825</integer>
  <key>installer_item_hash</key>
  <string>e5b30f7a5eee2470ad80b17149bd8f1df2f3225afdcf7b3427e3cf53fad1cbfd</string>
  <key>installer_item_location</key>
  <string>apps/adobe/DPS Desktop Tools CC2014-32.0.0.pkg</string>
  <key>installer_item_size</key>
  <integer>77645</integer>
  <key>minimum_os_version</key>
  <string>10.5.0</string>
  <key>name</key>
  <string>DPSDesktopToolsCC2014</string>
  <key>receipts</key>
  <array>
    <dict>
      <key>installed_size</key>
      <integer>77825</integer>
      <key>packageid</key>
      <string>com.organization.DPSDesktopToolsCC2014</string>
      <key>version</key>
      <string>32.0.0</string>
    </dict>
  </array>
  <key>uninstall_method</key>
  <string>removepackages</string>
  <key>uninstallable</key>
  <true/>
  <key>version</key>
  <string>32.0.0</string>
  <key>installs</key>
  <array>
    <dict>
      <key>CFBundleShortVersionString</key>
      <string>3.2.0</string>
      <key>path</key>
      <string>/Applications/DPS App Builder.app</string>
      <key>type</key>
      <string>application</string>
    </dict>
    <dict>
      <key>CFBundleShortVersionString</key>
      <string>3.4.3</string>
      <key>path</key>
      <string>/Applications/Adobe/Adobe Content Viewer.app</string>
      <key>type</key>
      <string>application</string>
    </dict>
    <dict>
      <key>CFBundleShortVersionString</key>
      <string>10.0.10.32</string>
      <key>path</key>
      <string>/Applications/Adobe InDesign CC 2014/Plug-Ins/Graphics/Digital Publishing.InDesignPlugin</string>
      <key>type</key>
      <string>bundle</string>
    </dict>
  </array>
  <key>blocking_applications</key>
  <array>
    <string>DPS App Builder</string>
    <string>Adobe Content Viewer</string>
    <string>Adobe InDesign CC 2014</string>
    <string>Creative Cloud Connection</string>
    <string>Adobe InDesign CS6</string>
    <string>Viewer Builder</string>
  </array>
  <key>preinstall_script</key>
  <string>#!/bin/bash

#If a user isn't logged in, fail
loggedInUser=`python -c 'from SystemConfiguration import SCDynamicStoreCopyConsoleUser; import sys; username = (SCDynamicStoreCopyConsoleUser(None, None, None) or [None])[0]; username = [username,""][username in [u"loginwindow", None, u""]]; sys.stdout.write(username + "\n");'`

if [ -z "${loggedInUser}" ]
then
   exit 1
fi

exit 0</string>
  <key>postuninstall_script</key>
  <string>#!/bin/bash

#Delete DPS App Builder and Adobe Content Viewer
/bin/rm -rf /Applications/DPS\ App\ Builder.app
/bin/rm -rf /Applications/Adobe/Adobe\ Content\ Viewer.app

exit 0</string>
  <key>installable_condition</key>
  <string>isUserLoggedIn == TRUE</string>
  <key>update_for</key>
  <array>
    <string>InDesignCC2014</string>
  </array>
  <key>requires</key>
  <array>
    <string>IsUserLoggedInCondition</string>
  </array>
  <key>unattended_install</key>
  <true/>
</dict>
</plist>

Epilogue
A technique like this should be avoided unless there’s no other way to get the software installed.  One possible issue would be that unless it’s the last installation in a chain of installations, adding an additional requirement to have a user logged in could have unusual effects with software installation dependencies (e.g. what happens if a piece of software that requires a restart depends on a piece of software that requires a user to be logged in?).  Not installing software at the Login Window is working against the design of Munki.

This is considerable effort to install a piece of software, and while it certainly seems to work there might be other issues I haven’t encountered yet.  If DPS Desktop Tools installation is something your organization is dependent on, you may wish to consider contacting your Adobe representative and sharing your opinions regarding the difficulty of installing DPS Desktop Tools.

Distributing Adobe CC 2014 via Munki

Continuing on the theme of packaging Adobe Creative Cloud (CC) 2014, let’s examine using Munki to deploy the software to computers.

Import and Prepping for Uninstallation
Munki’s preliminary CC 2014 support
Munki added initial explicit Creative Cloud (CC) support recently, adding the ability to specify a Creative Cloud Packager (CCP) uninstall pkg for removing the software. When importing the CCP package it’s important to specify the CCP uninstall pkg:

munkiimport /path/to/CCP_Install.pkg --uninstallerpkg /path/to/CCP_Uninstall.pkg

“version” keys in pkginfo files versus reality
When importing CCP pkgs, pay close attention to the version numbers that munkiimport determines and check to see if they correspond to what’s actually installed by the pkg. Updates baked into the original CCP pkg may not be recognized by munkiimport–for example, if InDesign CC 2014 with today’s most current update is imported, munkiimport suggests version “10.0” rather than the actually installed version of “10.1.0.71”. There’s no way to know exactly what software version is installed (CCP simply mentions “updates” and doesn’t give version numbers) without installing the CCP pkg.  Once the software is installed, either examine the application by selecting it in the Finder than then choosing File -> Get Info (or use makepkginfo–see the makepkginfo example under the “Installs arrays” heading below).  When the software version is determined, editing the “version” key in the pkginfo file to reflect reality should help reduce confusion.

Autoremove
I set “autoremove” to “true” in the pkginfo for each CCP pkg I imported.  Although this is likely organization-dependent, the need to be able to move software licenses from one computer to another made automatic removal the prudent choice.

Installs arrays
Providing an installs array allows Munki to more easily determine whether to software installation is necessary rather than depending on the Adobe uninstall databases.  Leaning on the documentation on this page in the Munki wiki (under the text that says “You can manually generate items to add…”), this could be used for InDesign CC 2014:

makepkginfo -f "/Applications/Adobe InDesign CC 2014/Adobe InDesign CC 2014.app"

And then copy and paste the installs array into the associated pkginfo.  However there are some instances where CCP pkgs need some extra attention:

  • There seem to be a set of unusual pkgs (typically CC titles initially released in the last few years, such as Lightroom and the Edge series of applications) where CCP wraps a pkg around an Adobe installer which is itself a wrapper around a pkg.  munkiimport currently is not able to determine receipts or installs arrays for this software, and thus managedsoftwareupdate considers them always installed and never attempts installation. If any of these pkgs are encountered, install the CCP pkg by hand and generate the installs array.  For example, install Edge Reflow CC and then run:
    makepkginfo -f "/Applications/Adobe Edge Reflow CC.app"

    Copy the installs array into the pkginfo for the Munki installer item.  Once a usable installs array is added to the pkginfo file, managedsoftwareupdate will properly evaluate the installation status of the installer item.

  • Edge Code CC includes extraneous information in all of its version keys. In this situation the best option I’m aware of is a MD5 hash of the Edge Code CC executable itself:
    makepkginfo -f "/Applications/Adobe Edge Code CC.app/Contents/MacOS/EdgeCode"
  • Gaming SDK doesn’t install anything that’s usable for Munki to evaluate for versions. In this case, have makepkginfo evaluate the pkg located inside the CCP pkg:
    makepkginfo "/path/to/GamingSDK_Install.pkg/Contents/Resources/Setup/GSDK1.4en_US/Adobe Gaming SDK 1.4.pkg"

    And include the receipts array in the Gaming SDK pkginfo.

When uninstallation is known to not work
Even with CCP uninstallation pkg support built into Munki, there are multiple CC applications that cannot be uninstalled using their CCP uninstall pkg. Under “Known behavior and issues” in the “Version 1.3” section of the Creative Cloud Packager Readme, there’s documentation about uninstallation of various applications failing.  For Munki, the solution is to use an uninstall_method of uninstall_script (rather than “AdobeCCPUninstaller” that’s generated by importing a CCP uninstallerpkg) which removes the application and the receipt, if installed.  The applications, deletion paths, receipts, and links to Adobe’s support saying this is a proper uninstallation (if I can find it) are below:

  • Edge Code Preview CC
    Path: “/Applications/Adobe Edge Code CC.app”
    Receipt: com.adobe.EdgeCode
  • Edge Inspect CC
    Path: “/Applications/Adobe Edge Inspect CC.app”
    Receipt 1: com.adobe.shadow.pkg
    Receipt 2: com.adobe.shadow.postflight.pkg
  • Edge Reflow Preview CC
    Path: “/Applications/Adobe Edge Reflow CC.app”
    Receipt: com.adobe.pkg.Reflow
  • Gaming SDK
    Path: “/Applications/Adobe Gaming SDK 1.4”
    Receipt: com.adobe.AdobeGamingSDK1.4.pkg
  • Lightroom 5 (Note the CCP uninstaller pkg works if a user is logged in)
    Path: “/Applications/Adobe Photoshop Lightroom 5.app”
    Receipt: com.adobe.Lightroom5
  • Muse (Note the CCP uninstaller pkg works if a user is logged in)
    Path 1: “/Applications/Adobe Muse CC 2014”
    Path 2: “/Library/Application Support/Adobe/Uninstall/Uninstall Adobe Muse CC 2014.app”
    Receipt: com.adobe.adobeMuseCc20142.AdobeMuseCC.pkg
  • Scout CC
    Path: “/Applications/Adobe Scout CC.app”
    Receipt: com.adobe.pkg.Scout

An example uninstall_script for Edge Reflow CC would be:

#!/bin/bash
pathToDelete="/Applications/Adobe Edge Reflow CC.app"
receipt=com.adobe.pkg.Reflow
rm -rf "${pathToDelete}"
pkgutil --forget "${receipt}"

Unserialization
While the installation of the serial number pkg is relatively straightforward, the uninstallation is not. Since the same serial number potentially could be used to serialize different suites, automatically removing a serial number when a particular software title is uninstalled isn’t a given.  Consider a situation where Premiere and InCopy are installed on the same computer. Per discussions with Adobe support, both Premiere and InCopy need to use the same volume serial number when installed together on the same computer.  The following could occur:

  1. Premiere is installed
  2. Premiere is serialized
  3. InCopy is installed
  4. InCopy is serialized
  5. InCopy is uninstalled
  6. InCopy is unserialized

Following the unserialization of InCopy, Premiere won’t run since Premiere and InCopy share the same serial number.  There needs to be a way to determine at uninstallation time if another installed program or suite depends on the same serial number. In the earlier post about packaging Adobe CC 2014 applications, I created serialization pkgs with the following Package IDs:

com.organization.AdobeCCCompleteSerial-VideoSerialNumber
com.organization.AdobeInCopyCCSerial-VideoSerialNumber

Munki’s preuninstall_script can unserialize the software, and then a “removepackages” uninstallation method works to remove the serialization file themselves.  To remove the volume serial number only when appropriate, a preuninstall_script such as the following can check for additional receipts to determine whether the serial number is in use by an additional pkg:

#!/bin/bash
#Location of unserialization utility
unserializer="/Library/Adobe Licensing/Adobe InCopy CC Serial - Video Serial Number/RemoveVolumeSerial"

#If more than one installed pkg is using the Video Serial Number
if [ `pkgutil --pkgs=com\.organization\..+VideoSerialNumber | wc -l` -gt 1 ]
then
#Another software installation is using this serial number, do not unserialize
  echo Receipts found that use the serial number, not unserializing
  exit 0
else
#We're the last one out, unserialize and turn out the lights
  echo No other serialization receipts found, unserializing
  "${unserializer}"
fi

Setting “autoremove” to true for the pkginfo for the serialization pkg causes the serialization to be removed when not intentionally installed on a computer.

Controlling serialized versus unserialized installation
Gathering the individual-title CCP software packages is a good use of Munki’s included_manifest feature. This allows for multiple CCP pkgs (or other pkgs) to all be installed as one collection of software.  An example included manifest named “included-adobe-CompleteCC2014” could include (in part):

<key>managed_installs</key>
<array>
  <string>PhotoshopCC2014</string>
  <string>IllustratorCC2014</string>
  ...
  <string>PreludeCC2014</string>
  <string>MediaEncoderCC2014</string>
</array>

Attaching licenses to software is a bit more of a challenge–sometimes we do want the serialization to occur, other times we don’t. There are two ways I can see to handle this:

  • Add both the included_manifest for the software installation and a managed_install for the serialization pkg to the computer’s manifest (e.g. included_manifest of “included-adobe-CompleteCC2014” and a managed_install of “AdobeCCCompleteSerial-VideoSerialNumber”). This requires adding two separate installer items for each serialized installation.
  • Set up the “requires” array in the serialization pkg’s pkginfo to require all the software that’s intended to be serialized (e.g. set up the pkginfo for “AdobeCCCompleteSerial-VideoSerialNumber” to “require” the software that’s intended to be serialized).  This requires adding only a single installer item for a serialized installation.

I chose the latter and went a step further–since I didn’t want an included_manifest for an unserialized installation and a managed_install for a serialized installation, I created an included_manifest that only included the serialization pkg (thus a manifest named “included-adobe-CompleteCC2014” and a manifest named “included-adobe-CompleteCC2014Serialized” exist). It adds a level of indirection, but keeps things more consistent since all software installations and removals occur within included_manifests.  Thus the following workflow is possible:

  • Munki client needs InCopy, but does not need a serial number
    • Client manifest has “included-adobe-InCopyCC2014” manifest added to its included_manifests array
      • manifest “included-adobe-InCopyCC2014” has managed_install of “InCopyCC2014”
    • Munki client installs InCopy
  • The same Munki client needs CC Complete, but does not need a serial number
    • Client manifest has “included-adobe-CompleteCC2014” manifest added to its included_manifests array
      • manifest “included-adobe-CompleteCC2014” has managed_installs for CC Complete 2014 software
    • Munki client installs CC Complete 2014 software
  • The same Munki client needs a serial number for InCopy CC 2014 and CC Complete 2014
    • Client manifest has “included-adobe-InCopyCC2014” and “included-adobe-CompleteCC2014” manifests removed from its included_manifests array and “included-adobe-InCopyCC2014Serialized” and “included-adobe-CompleteCC2014Serialized” manifests added to its included_manifests array
      • manifest “included-adobe-InCopyCC2014Serialized” has managed_install of “AdobeInCopyCCSerial-VideoSerialNumber”
        • pkginfo for “AdobeInCopyCCSerial-VideoSerialNumber” “requires” “InCopyCC2014”
      • manifest “included-adobe-CompleteCC2014Serialized” has managed_install of “AdobeCCCompleteSerial-VideoSerialNumber”
        • pkginfo for “AdobeCCCompleteSerial-VideoSerialNumber” “requires” CC Complete 2014 software
    • Munki client determines InCopy CC 2014 and CC Complete 2014 software are already installed.  Munki client installs both serialization pkgs for InCopy CC 2014 and CC Complete 2014
  • The same Munki client no longer needs CC Complete 2014
    • Client manifest has “included-adobe-CompleteCC2014Serialized” manifest removed from its included_manifests array (leaving “included-adobe-InCopyCC2014Serialized” manifest in the included_manifests array)
    • Munki client uninstalls CC Complete 2014 software
    • Munki client uninstalls managed_install “AdobeCCCompleteSerial-VideoSerialNumber”, however serial number is not actually removed since  “AdobeInCopyCCSerial-VideoSerialNumber” is installed
    • Munki client is left with a serialized installation of InCopy CC 2014