Phased Deployments: How are you handling?

Contributor II

Like I'm sure many of you we are looking at rolling out new software deployments in a phased manner, across 4 separate groups: testing, IT, users, management. I had started to subdivide our users into static JSS groups, but then realized this would require manually modifying scope at key days/times vs having them fire off automatically.

How are you all handling phased rollouts of your software deployments? Duplication of deployment policies scoped to specific user groups and triggered on specific time periods? Spiffy leveraging of magical JSS smart groups?

For example: the latest Java 2013-003 release. I have a "Needs Java 2013-003" smart group, but I also need to limit deployment to a specific/static group of Macs comprised in my 4 different static computer groups. How do I limit to both the dynamic Needs Java 2013-003 group AND one of the 4 static computer groups?



Contributor II

The way I did it last seemed to work decent. I setup a standard installer policy, duplicated it twice. The original was set to a specific group, to start on a specific time. The second policy was scoped to a different group, and set to start a specific date/time. Same for the third.

Every other day i went back in and moved the smart groups from the #2 & #3 to the original policy (as if Java was installed it would fall out of the smart group). Then change the #2 & #3 policy smart groups to be the next two groups.

Not the prettiest way, but I had over 10 unique groups to handle the installs on, so two at a time was doable.

You could create a manual EA that says what upgrade group it is part of, and so you could reference them dynamically, if you really want to have a dynamic/static group. We used user/department so this wasn't an issue.

Legendary Contributor II

I'm not sure how well this will work in your case, but you could try creating Smart Groups that use your base criteria as usual, but also throw in the JSS ID number range, to split up the systems. For example, say you have 1000 Macs and wanted to phase this out over a number of days and over 4 groups, set up the 4 Smart Groups using something like:

JSS Computer ID | less than | 251
JSS Computer ID | more than | 250 & JSS Computer ID | less than 501
JSS Computer ID | more than | 500 & JSS Computer ID | less than 751
JSS Computer ID | more than | 750 & JSS Computer ID | less than 1001

You can then start adding those groups in every couple of days to the policy, or even just set up 4 policies like ctangora described with set start times and scope each group to one.

And if you're environment is like ours and you have some older Macs that have dropped off the grid for whatever reason, you could throw the Last Check In time criteria to narrow them down further.

Edit: In looking back at your original post, I see that I kind of misread what you're looking for. Seems you want to phase it out progressively from testers to all users and some groups in between. In that case, I guess using department or some other criteria would make more sense than using JSS ID.

Contributor II

Thanks guys.

@Chris: I have considered having policies that I manually add/remove smart groups from in order to push out X software to Y machines over time, but I really wanted to make sure I had something more automated, in the case where I am setting a particular update to fire off in sequence, without relying on me or others making a change on particular days/times.

@Mike: I've seen the option to use the JSS CID come up before in other discussions, but since our computers have been enrolled across all different levels and times that would be about as tedious as scoping by user, since the CIDs would not be confined to any specific range.

That said, I've found 2 possible solutions to this scenario:

1) Scope policy by user-fields pulled into the computer's Location section from our AD that may define what phase they should fall in. Ex: for Management / Phase 4 group Location->Position = "director" or "vice president" but not like department = "IT". This has the advantage of dynamically "moving" a user into a new deployment phase if/when they are promoted, but disadvantage of using fuzzy logic that may not always match up to our simple static group memberships... and I still have not found a way to get a machine scoped to X smart group, but not if they are in Y smart group.

2) Mike: I think the script you posted over off the feature requests section may do just the trick for what I need, essentially combining the option of multiple group criteria through the API. I'll definitely give this a try and let you know how it works out (source:


Contributor II


@Mike, your script to collect all group membership is invaluable in permitting more advanced smart group organization, however I am still at a loss to determine a way to scope a policy to X group AND Y criteria. Seem the only way to limit a policy is by setting as self service policy, since that forces user login, yet even that only allows limitation by user and AD group. Why not computer group as well?

Increasingly considering I may need to dump Casper for Munki when it comes to more targeted software deployment phasing. Otherwise go back to the business of creating 4 separate smart groups + 4 separate policies for every software deployment we want to roll out.

Any other creative tips/tricks for limiting Casper policy scope?

Legendary Contributor II


First, I'm glad the script/EA for group membership is helping you. When you say "I am still at a loss to determine a way to scope a policy to X group AND Y criteria." can you explain what you mean exactly?

Is it not possible to set regular criteria settings in a Smart Group and also add in the EA for Group Membership is Like "Group Name" I'm not using my own process so I don't have a good way to test anything out. Just taking guesses, but I assumed something like that would work.
I may also be misinterpreting what you're really looking for.

Contributor II

@Mike: the short answer is yes, but I was looking for a way to avoid creating 4 separate smart groups (to limit by installed SW and computer group) and 4 separate policies (to deploy by date/time) for each and every software deployment/patch that we want to push out.

What I was hoping for was a way to apply a policy to:

  • computers of smart group "needs Java 2013-003"
  • but only those within group "Phase1-Testing."

Obviously if I add more than one group in a policy I'm merely adding more machines (OR) vs further limiting the scope down (AND).

Having the ability to scope policy by X and Y would allow me to create my 4 deployment groups, then reuse those as limiting criteria for each/every new SW deployment we push out over time.

Does that make sense? Just wrapping my own head around all possible group vs policy logic has got my head spinning so I may not be explaining it as best as I could.

Legendary Contributor II


No worries, This kind of stuff can be headache inducing for sure :) I'm still not 100% clear on what you described, but I have the general idea I think.
I will say that although I originally designed and envisioned the script to be used within an Extension Attribute, I'll note that @acdesigntech is also using the code block within custom shell scripts. You may be able to do something similar - create a special script using passed parameters from the JSS (to make it re-usable) that would only run policies based on whether it finds the Mac its running against is a member of a group or groups. Those groups can be one of the parameters assigned to the script, as well as something like what policy it should call if it finds the Mac in said group. Then either exit or go ahead with the running the policy itself.
One advantage of having it all contained within a script is that you may not need to create all those separate Smart groups, just the different policies that use that same script.
Another advantage is you could use some && operands in if/then statements to determine if a Mac is a member of all the groups you're trying to scope to.

For example:

if [[ "$Groups" =~ "needs Java 2013-003" ]] && [[ "$Groups" =~ "Phase1-Testing" ]]; then
    jamf policy -id <id>
    exit 0

Would that help?

Contributor II

It should. I added what you have above prefixed with part of the EA script to pull the computer groups. Unfortunately it appears that a policy (containing the script) that calls another policy is causing problems with DP share mounting. Appears to be both scripts trying to mount the DP at same time? Ever seen that before?


verbose: Parsing Policy Run Script (373)...
Executing Policy Run Script
verbose: Will mount at /Volumes/CasperSoftware$ 1
    Mounting smb://$ to /Volumes/CasperSoftware$ 1...
verbose: Result of mount attempt: mount_smbfs: mount error: /Volumes/CasperSoftware$ 1: File exists

    Error: Could not mount a distribution point.

Legendary Contributor II

Don't think I have seen that before. The only reason it would/should have trouble is if the share was mounted with different credentials than the jamf binary expects it to be. If its already mounted and its balking at that, I'd be inclined to think this is a bug. It doesn't make any sense.

Contributor II

Well FWIW, DP share mounting errors appear to only be happening on policies set to install packages / run scripts. If I scope the conditional policy to something like Add X Dock items it does go through. Strange.

Legendary Contributor II

@Clif - Are you not able to use http/s downloads? It would likely avoid the error you're seeing.

Valued Contributor II

Dummy receipts.

Create a policy that touches a file in /Library/Application Support/JAMF/Receipts. Name the file something like
Have this policy do a recon after executing. Scope it to the relevant group.

Then, when you create your Smart Group for "Needs Java 2013-003", you can also use the criteria "Receipts Information, Packages installed by Casper Suite" and then your file you created above.

This is tricky/a bit "hacky" but it works in these "compound application" situations...

Contributor II

@Mike SMB-only file shares in this environment unfortunately.

@Robert interesting workaround. Having already implemented Mike's Casper groups EA I suspect that may already be providing the same functionality for us as those dummy receipts, no?

Running out of ideas. FWIW, this is the updated script above I'm using in case I'm doing something clearly wrong here:

# Run policies by group membership. 
# Courtesy mm2270 @

# Read in the parameters
policy=$4               # policy id you want to execute
group1=$5               # 1st group/criteria you want to match
group2=$6               # 2nd group/criteria you want to match 

MAC=$( networksetup -getmacaddress en0 | awk '{ print $3 }' | sed 's/:/./g' )

JSSGroups=$( curl -s -u apiread:password$MAC 
| xpath //computer/groups_accounts/computer_group_memberships[1] 
| sed -e 's/<computer_group_memberships>//g;s/</computer_group_memberships>//g;s/<group>//g;s/</group>/\n/g' )

if [[ "$JSSGroups" =~ "$group1" ]] && [[ "$JSSGroups" =~ "$group2" ]]; then
    jamf policy -id "$policy" -verbose
    exit 0

Legendary Contributor II

@Clif - So, if I understand correctly, the script and process should work for you except for the fact that, since you have to use SMB shares, you're running into the problem that the script causes the CasperShare to mount, and when it tries to call the policy, it balks since the share is already mounted. Is that essentially it?

If so, I think I know how you can get around this, although its a slight compromise in flexibility.

Here's what I'd try-
- Take your script above and wrap it up in Composer to deploy it down to your Macs to s specific location, say something like /var/casper/scripts/ or wherever you'd like
- Deploy that pkg in a policy to get the script down to your Macs. You can even build an EA to gather machines that don't have the script if you want.
- Now set up your policy to run the script, but use the Run Command field in the policy with something like this-

/usr/sbin/jamf runScript -script "" -path /var/casper/scripts/ -p1 "policyid" -p2 "group1" -p3 "group2"

The above will call the script directly and pass the supplied parameters to it using the jamf binary on the system, rather than needing to mount a share and download a script. Note that -p1 refers to $4 and -p2 refers to $5, etc.
Run Command is as close to ARD's Send Unix Command function as the Casper Suite has.

This should avoid the issue since it would only mount the share if the script finds the Mac in the groups you've specified and goes ahead and calls the policy by its id.

I haven't tested the above, so I'm only making an assumption, but hopefully a good assumption. :)
Give it a try if you can and let us know if that solves your issue.

New Contributor III

So, I know I'm responding to something super old, but I have a similar need and came up with the following solution:

1) An extension attribute called "DeploymentWave" that is populated by a script.

Script Content:


if [ ! -f "/var/db/.deploymentWaveSet" ]; then
    deploymentWave=$(jot -r 1 1 5)
    touch /var/db/.deploymentWaveSet

echo "<result>$deploymentWave</result>"

In my case, I want 5 waves, so the "jot -r 1 1 5" command assigns a random number from 1-5 for the extension attribute deploymentWave on each machine.

The ".deploymentWaveSet" file is simply a flag that tells the script that the value has already been set for a given machine.

To reassign a machine, or to "spin" the memberships and randomize all machines again simply run a script to delete the .deploymentWaveSet filesystem flag from each machine (and have the machines re-run recon).

From here it's just a matter of creating 5 (or however many) smart groups that look at the value of the extension attribute (DeploymentWave=1, etc).

Hope this helps someone!