Skip to content
Chris Lasell edited this page Apr 8, 2016 · 10 revisions

d3 Client

A d3 client is a computer managed by Casper, that uses d3 to do local package management. It's also the command-line tool called d3 used for installing d3 packages, and working with receipts on the computer.

d3 command-line utility

The d3 command is the heart of d3 and us used for piloting, installing, uninstalling, syncing, and generating various lists and info. Use d3 help to see the usage summary. Other than showing the help, d3 must be used with root privileges.

The general form of a d3 command-line is sudo d3 [options] action [target [...]]

  • An action is always required, and tells d3 what you want to do, e.g. 'install', 'sync', 'list-available', and so on.
  • The target(s) are thing or things you want to perform the command with
  • The options can change the behavior of the command, or provide extra info.

Throughout this page, the 'sudo' is implied.

For a summary of all actions, targets, and options, see the d3 Help Summary

Receipts

d3 keeps track of what's installed by maintaining a set of receipts locally. These receipts are separate from the JSS package receipts, and also different from the Apple package receipt system available via pkgutil. A d3 receipt stores all info needed to work with the package after installation. For details about how receipts work, see the Receipts page.

Installing packages

Installation is done with the install action: d3 install <basename>. This causes the currently live package for the basename to be installed.

Packages with one or more 'auto-groups' will be automatically installed on apropriate computers when they sync.

During package installation, d3 will first check that no prohibiting process is running, and then might uninstall older editions of its basename. Then d3 will run any pre-install script. If the script exits successfully, the package is installed using jamf install. If the install was successful, any post-install script is run.

In order to install a pacakge, d3 needs to know the name of a non-root 'admin' who is doing the install. If d3 can't figure out a name on it's own, it must be provided with the -a/--admin option. When doing a d3 install in a script or Casper policy or any other automated way other than syncing, use the --admin option to provide the name of the script or policy doing the install.

Piloting

In order to test a package before it's made live, you can install it on a test machine by specifying its edition: d3 install <edition>. d3 will then install that package and it's receipt will have the status 'pilot'.

If the pilot's edition becomes live on the server, the receipt will be updated to reflect that at the next sync.

If a newer edition of the pilot's basename becomes live, the new live one will be installed at the next sync, and the basename will no longer be in pilot on that machine.

If you need to keep a specific edition on the computer, regardless of what becomes live, you must freeze the receipt so it's ignored during the auto-update phase of syncing.

Other installs

Sometimes you may want to install a deprecated or skipped package.

In either of those cases, you'll need to use the --force option to make d3 do something it normally wouldn't. So: d3 install <edition> --force

In this case, you might also want to use --freeze, or else the package will be updated to the live version at the next sync.

Uninstalling

If a receipt is marked as removable, then d3 uninstall <basename> will uninstall it. If it is not removable, then it can't be uninstalled, even with force.

Uninstalling will first attempt to use the jamf uninstall command, which deletes the files listed in the packages index. (All d3 packages are indexed in Casper automatically when they are added).

If the receipt is marked as missing, or the JSS isn't available, and force is used, d3 will use the Apple package receipt to find the index, if the installer was a .pkg. If it was a .dmg, and force was used, no index is available, but the d3 and JAMF receipts will be deleted.

Conditional installs and uninstalls

While .pkg installers might have internal pre- and post- install scripts, .dmg installers do not. Also, while Casper policies can run Casper scripts before and after package (un)installation, the process can't easily be stopped if the pre- script fails.

d3 provides pre- and post-install, and pre- and post-remove scripts. If the pre-install or pre-remove scripts fail, the un/installation won't happen.

These scripts are just Casper scripts, and under the hood, they are run via the jamf runScript command.

See Packages - pre- and post- scripts for a discussion of conditional installs and uninstalls, as well as the special meaning of pre- scripts exiting with status 111.

--admin option

Whenever installing a package, d3 needs to know who is doing it, or what's automating it. This name is reported in the output of the 'list-installed' action. To be meaningful, the name cannot be 'root', or any of the words defined in the 'client_prohibited_admin_names' setting of the d3.conf file.

For auto-installs and updates during a sync, the string 'auto-installed' is used, but for manual or scripted installs, d3 needs to know. Even though it is running as root, d3 tries to figure out who's running the command, by looking at the environment for SUDO_USER or SSH_CLIENT_USER. If neither are set, or they return a non-valid word, then it will raise an error. To avoid this, provide a name with the --admin/-a option.

The name need not be a real admin's name, it just needs to be something meaningful to indicate how or why the package was installed. For example, if the pre-install script for package 'transmogrifier-4-12' installs another package, it can use d3 install transmogrifier-helper --admin transmogrifier-pre-install. If you have a policy that installs a the live 'foo' onto some finely-scoped machines, the policy could execute d3 install foo --admin foo-deploy-policy

Syncing

Syncing is the heart of d3's automation. When the command d3 sync is run on a client, these things happen:

  • Receipts are updated

    Any applicable changes that have been made to the matching packages on the server, are updated in the receipt. See Receipts - Updating of receipts

    One of the things updated is the receipts status. This means that if a receipt is in pilot, and the matching package becomes live, the receipt becomes live also, and is once again able to be auto-updated.

  • Auto-updating happens

    For all non-frozen receipts, if the currently-live edition for that basename is newer, the update is installed. This is the core function of d3 - the automatic installation of new versions of things when they are released on the server.

  • New scoped packages are installed

    Any newly-available live package on the server, which has one of this machine's groups in its auto-groups list, is installed. This could happen because a new basename became live, or because the auto-groups for a package changed, or because the machine's group memberships have changed.

    See also: auto groups

  • Expiration happens

    If a receipt is exprirable and all the conditions are correct, the receipt is uninstalled

Syncing is controlled by a launchd job or Casper policy to run at regular intervals, but can be run manually any time with d3 sync.

Freezing

Receipts can be frozen so that they don't auto-update during sync. This is useful when you want to hold a group of clients at a deprecated or skipped edition for some time, while making a newer edition live for everyone else.

To freeze a receipt, use d3 freeze <basename>

To freeze immediately at install time, d3 install <basename|edition> --freeze

There are three ways to 'unfreeze' a receipt:

  • d3 thaw <basename>
  • manually install any edition of the basename (note if you install a pilot, it'll be in pilot and still won't auto update)
  • uninstalling the receipt

Scoping

d3 itself provides basic scoping via a package's auto-groups and excluded-groups. This can handle most of the scoping needs for most packages.

If more complex scoping is needed, one method is to assign no auto- or excluded-groups, and use a fully-scoped Casper policy to perform the 'd3 install' command.

Force

The --force option to d3 causes it to do many things that it wouldn't normally do.

For example, if a package is excluded for one of the machine's groups, it can still be installed or piloted with --force.

Excluded packages normally don't show up in the list of pacakges available for a computer with d3 list-available. Using --force will cause all live packages to be listed.

There are some things d3 can't do, even with force:

  • Installing on an OS not in the list of allowed OS's for the package
  • Installing on a CPU type not allowed by the package
  • Uninstalling a non-removable receipt

Expiration

Expiration is d3's ability to uninstall software automatically when it hasn't been used in some period of time. Expirations happen during sync. From d3's perspective 'used' means 'brought to the foreground in a console session'.

Two attributes of Packages and Receipts are related to expiration:

  • expiration

    This is an integer representing the number of days of disuse required before a package is expired. For example, if the expiration is 30, the package will be removed after 30 days of disuse. Setting the expiration to zero (the default) means the package never expires.

  • expiration_path

    This is the path to the executable that must come to the foreground to be counted as "use"

    For example, a package that installs /Applications/Foobar.app, might have expiration_path of /Applications/Foobar.app/Contents/MacOS/Foobar

Since an erroneous expiration could be very disruptive to the end user, many conditions must be true before a receipt is uninstalled.

  • Expirations must be allowed in the d3.conf file.
  • d3 must have a connection to the server, no offline expirations
  • d3RepoMan must be running - it must always be running.
  • The usage files maintained by d3RepoMan must exist
  • The usage files maintained by d3RepoMan must have been updated within the last 24 hours. (If nothing's come the the foreground in 24 hours, we assume somethings awry, and wait till the next sync)
  • The receipt must be removable
  • The receipt must have an expiration value greater than zero
  • The last time the expiration path came to the foreground must be more than days ago.

d3RepoMan

d3RepoMan is a background process that records a timestamp every time an application comes to the foreground in the machine's UI. It is required to use d3's [expiration]#(expiration) feature. It allows the use of that feature without turning on Casper's 'application usage logging', which stores the data on the server.

d3RepoMan is launched at login by a system-wide Launch Agent, and runs as the user logged in. It writes a different plist for each user in /Library/Application Support/d3/Usage/. Those plists are used by the sync process as it performs expirations to determine when the expiration path was last brought to the foreground. Being in the foreground now counts as 'use' even if there are no timestamps in the usage plists.

Post-expiration policy

In the d3.conf file you can specify a Casper policy to run after any receipts are expired. This can be used to notify users or admins, or any other automatic task you'd like to do when things are expired on a computer.

See Admin - Environment variables for how to pass info about the expirations to the policy.

Puppytime

Some packages require a reboot after they are installed. d3 handles these using a system called 'puppytime' - a name inherited from a tool used by Pixar to automate such installations long before d3 was written.

The original tool would display a slide-show of cute puppy images while the installation(s) were happening, after logout and before reboot. This let the users know that something was happening, otherwise they would often hard-reboot the computer because they thought it was hung. It also made them smile to see the puppies.

When d3 'installs' a package requiring reboot, info about the package is added to the 'puppy queue' to be installed at the next logout. If desired, a Casper policy can be triggered when the item is added to the queue, and that policy can notify the user to log out as soon as convenient.

At logout, another Casper policy runs the command puppytime. The puppytime command looks at the queue, and exits immediately if the queue is empty.

If there are items in the queue, an opt-out window is shown, allowing the user a few seconds to abort processing the queue. Once the installations begin, the slideshow begins.

The default images that come with d3 are still puppies, however they can be customized easily. See the d3.conf file for details about customizing your slideshow.

puppy queue

Only one edition per basename can be in the puppy queue at a time. If you add a newer edition, it will replace any older one that's already there. However if you try to add an older edition, you'll get an error. Using force will add the older one regardless.

The contents of the puppy queue can be listed with with d3 list-queue and items therein can be removed with d3 dequeue basename

rebooting after puppytime

Of course, the whole reason for installing at logout is so the machine can be rebooted after the installs are finished.

By default, puppytime will reboot the machine using shutdown -r now.

However, you can have puppytime run a Casper policy instead.

This would be useful if you'd like to handle the reboot some other way (such as with an authenticated reboot for FileVaulted computers) or perform some other tasks before the reboot.

The important thing is that the policy MUST reboot the machine. If puppytime sees a policy available, it will run it, but not attempt the reboot itself.

WARNING: don't use this policy in places of a post-install script. Its purpose is to reboot the machine regardless of what packages were installed.