Module: Xolo::Server::Mixins::VersionJamfAccess

Included in:
Version
Defined in:
lib/xolo/server/mixins/version_jamf_access.rb

Overview

This is mixed in to Xolo::Server::Version to define Version-related access to the Jamf Pro server

Constant Summary collapse

JAMF_SMART_GROUP_NAME_INSTALLED_SFX =

The group of macs with this version installed is named the full prefix plus this suffix.

'-installed'
JAMF_POLICY_NAME_MANUAL_INSTALL_SFX =

The policy that does initial installs on-demand (via ‘xolo install <title> <version’) is named the full prefix plus this suffix.

'-manual-install'
JAMF_POLICY_NAME_AUTO_INSTALL_SFX =

The policy that does auto-installs is named the full prefix plus this suffix. The scope is changed as needed when a version’s status changes

'-auto-install'
JAMF_POLICY_NAME_AUTO_REINSTALL_SFX =

The policy that does auto-re-installs is named the full prefix plus this suffix. The scope is changed as needed when a version’s status changes

'-auto-reinstall'
JAMF_AUTO_REINSTALL_WAIT_SECS =

How long to wait after a pkg re-upload before creating/enabling/flushing the auto-reinstall policy See TODO in #wait_to_enable_reinstall_policy

15 * 60

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.extended(extender) ⇒ Object

when this module is extended



170
171
172
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 170

def self.extended(extender)
  Xolo.verbose_extend extender, self
end

.included(includer) ⇒ Object

when this module is included



165
166
167
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 165

def self.included(includer)
  Xolo.verbose_include includer, self
end

Instance Method Details

#activate_patch_version_in_jamfvoid

This method returns an undefined value.

Wait until the version is visible from the title editor then assign the pkg to it in Jamf Patch, and create the patch policy.

Do this in a thread so the xadm user doesn’t wait up to ?? minutes.



1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
1323
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1307

def activate_patch_version_in_jamf
  # don't do this if there's already one running for this instance
  if @activate_patch_version_thread&.alive?
    log_debug "Jamf: activate_patch_version_thread already running. Caller: #{caller_locations.first}"
    return
  end

  msg = "Jamf: Will assign Jamf pkg '#{jamf_pkg_name}' and create the patch policy when this version becomes visible to Jamf Pro from the Title Editor."
  progress msg, log: :debug

  @activate_patch_version_thread = Thread.new do
    log_debug "Jamf: Starting activate_patch_version_thread waiting for version #{version} of title #{title} to become visible from the title editor"

    start_time = Time.now
    max_time = start_time + Xolo::Server::MAX_JAMF_WAIT_FOR_TITLE_EDITOR
    start_time = start_time.strftime '%F %T'

    did_it = false

    while Time.now < max_time
      sleep 15
      log_debug "Jamf: checking for version #{version} of title #{title} to become visible from the title editor since #{start_time}"

      # check for the existence of the jamf_patch_title every time, since it might have gone away
      # if the title was deleted while this was happening.
      next unless title_object.jamf_patch_title(refresh: true) && title_object.jamf_patch_title.versions.key?(version)

      did_it = true
      break
    end

    if did_it
      assign_pkg_to_patch_in_jamf
      # give jamf a moment to catch up and refresh the patch title
      # so we see the pkg has been assigned
      sleep 2
      title_object.jamf_patch_title(refresh: true)

      create_jamf_patch_policy
      msg = "Jamf: Version '#{version}' of title '#{title}' is now visible in Jamf Pro. Package assigned and Patch policy created."
      log_info msg, alert: true
    else
      msg = "Jamf: ERROR: Version '#{version}' of title '#{title}' has not become visible from the Title Editor in over #{Xolo::Server::MAX_JAMF_WAIT_FOR_TITLE_EDITOR} seconds. The package has not been assigned, and no patch policy was created."
      log_error msg, alert: true
    end
  end # thread
  @activate_patch_version_thread.name = "activate_patch_version_thread-#{title}-#{version}"
end

#assign_pkg_to_patch_in_jamfvoid

This method returns an undefined value.

Assign the Package to the Jamf::PatchTitle::Version for this Xolo version. This ‘activates’ the version in Jamf Patch, and must happen before patch policies can be created

Jamf::PatchTitle::Version objects are contained in the matching Jamf::PatchTitle, and to make or save changes, we have to fetch the title, update the version, and save the title.

NOTE: This can’t happen until Jamf see’s the version in the title editor otherwise you’ll get an error. The methods that call this should ensure the version is visible.



1370
1371
1372
1373
1374
1375
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1370

def assign_pkg_to_patch_in_jamf
  log_info "Jamf: Assigning package '#{jamf_pkg_name}' to patch version '#{version}' of title '#{title}'"

  jamf_patch_version.package = jamf_pkg_name
  title_object.jamf_patch_title.save
end

#configure_jamf_auto_install_policy(pol) ⇒ Object

Configure the given policy as the auto-install policy for this version

Parameters:

  • pol (Jamf::Policy)

    the policy to configure



533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 533

def configure_jamf_auto_install_policy(pol)
  pol.category = Xolo::Server::JAMF_XOLO_CATEGORY
  pol.set_trigger_event :checkin, true
  pol.set_trigger_event :custom, Xolo::BLANK
  pol.frequency = :once_per_computer
  pol.retry_event = :checkin
  pol.retry_attempts = 5
  pol.recon = false

  pol.package_names.each { |pkg_name| pol.remove_package pkg_name }
  pol.add_package jamf_pkg_name

  # exclusions are for always
  set_policy_exclusions pol

  # set the scope targets based on status
  if pilot?
    set_policy_pilot_groups pol
  else
    set_policy_release_groups pol
  end

  # enable or disable based on status
  if pilot? || released?
    pol.enable
  else
    pol.disable
  end
end

#configure_jamf_auto_reinstall_policy(pol) ⇒ Object

Set the proper config for the auto reinstall policy

Parameters:

  • pol (Jamf::Policy)

    the policy to configure



841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 841

def configure_jamf_auto_reinstall_policy(pol)
  pol.category = Xolo::Server::JAMF_XOLO_CATEGORY
  pol.set_trigger_event :checkin, true
  pol.set_trigger_event :custom, Xolo::BLANK
  pol.frequency = :once_per_computer
  pol.recon = false
  pol.retry_event = :checkin
  pol.retry_attempts = 5
  pol.scope.set_targets :computer_groups, [jamf_installed_group_name]

  # exclusions are for always
  set_policy_exclusions pol

  pol.package_names.each { |pkg_name| pol.remove_package pkg_name }
  pol.add_package jamf_pkg_name

  # NOTE: this policy is not enabled by default - it will be enabled
  # if/when the pkg for the policy is re-uploaded
  pol.enable if reupload_date.is_a? Time
end

#configure_jamf_installed_group(grp) ⇒ void

This method returns an undefined value.

Set the configuration of the given smart group as needed for the jamf_installed_group

Parameters:

  • grp (Jamf::ComputerGroup)

    the group to configure



725
726
727
728
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 725

def configure_jamf_installed_group(grp)
  progress "Jamf: Setting criteria for smart group '#{grp.name}'", log: :info
  grp.criteria = Jamf::Criteriable::Criteria.new(jamf_installed_group_criteria)
end

#configure_jamf_manual_install_policy(pol) ⇒ Object

Configure the given policy as the manual-install policy for this version

Parameters:

  • pol (Jamf::Policy)

    the policy to configure



627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 627

def configure_jamf_manual_install_policy(pol)
  pol.category = Xolo::Server::JAMF_XOLO_CATEGORY
  pol.set_trigger_event :checkin, false
  pol.set_trigger_event :custom, jamf_manual_install_trigger
  pol.frequency = :ongoing
  pol.recon = false

  pol.package_names.each { |pkg_name| pol.remove_package pkg_name }
  pol.add_package jamf_pkg_name

  set_policy_to_all_targets pol
  set_policy_exclusions pol

  # These policies shouldn't be in ssvc
  # only the title's jamf_manual_install_released_policy is
  pol.remove_from_self_service if pol.in_self_service?
  pol.enable
end

#create_in_jamfObject

Create everything we need in Jamf



186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 186

def create_in_jamf
  # this will create the JPackage object
  jamf_package

  # The
  # - jamf_installed_group
  # - jamf_auto_reinstall_policy
  # aren't needed until there's a pkg re-upload
  # and they will be created then if they doesn't already exist

  # these will create the policies
  jamf_auto_install_policy
  jamf_manual_install_policy

  activate_patch_version_in_jamf
end

#create_jamf_auto_install_policyJamf::Policy

The auto install policy is triggered by checkin but may have narrow scope targets, or may be targeted to ‘all’ (after release) Before release, the targets are those defined in #pilot_groups_to_use

After release, the targets are changed to those in title_object#target_group

This policy is never in self service

Returns:

  • (Jamf::Policy)

    the auto install policy for this version



513
514
515
516
517
518
519
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 513

def create_jamf_auto_install_policy
  progress "Jamf: Creating Auto Install Policy: #{jamf_auto_install_policy_name}", log: :debug
  pol = Jamf::Policy.create name: jamf_auto_install_policy_name, cnx: jamf_cnx
  configure_jamf_auto_install_policy(pol)
  pol.save
  pol
end

#create_jamf_auto_reinstall_policyJamf::Policy

The auto rionstall policy, for when a pkg is re-uploaded for this version.

Returns:

  • (Jamf::Policy)

    the auto install policy for this version



821
822
823
824
825
826
827
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 821

def create_jamf_auto_reinstall_policy
  progress "Jamf: Creating Auto Re-Install Policy: #{jamf_auto_reinstall_policy_name}", log: :debug
  pol = Jamf::Policy.create name: jamf_auto_reinstall_policy_name, cnx: jamf_cnx
  configure_jamf_auto_reinstall_policy(pol)
  pol.save
  pol
end

#create_jamf_installed_groupJamf::ComputerGroup

Create the smart group of macs with this version installed

Returns:

  • (Jamf::ComputerGroup)

    the smart group.



694
695
696
697
698
699
700
701
702
703
704
705
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 694

def create_jamf_installed_group
  progress "Jamf: Creating smart group '#{jamf_installed_group_name}'", log: :info

  @jamf_installed_group = Jamf::ComputerGroup.create(
    name: jamf_installed_group_name,
    type: :smart,
    cnx: jamf_cnx
  )
  configure_jamf_installed_group @jamf_installed_group
  @jamf_installed_group.save
  @jamf_installed_group
end

#create_jamf_manual_install_policyObject

The manual install policy is always scoped to all computers, with exclusions

The policy has a custom trigger, or can be installed via self service



606
607
608
609
610
611
612
613
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 606

def create_jamf_manual_install_policy
  progress "Jamf: Creating Manual Install Policy: #{jamf_manual_install_policy_name}", log: :info

  pol = Jamf::Policy.create name: jamf_manual_install_policy_name, cnx: jamf_cnx
  configure_jamf_manual_install_policy(pol)
  pol.save
  pol
end

#create_jamf_packageJamf::JPackage

Returns Create the Jamf::JPackage object for this version and return it.

Returns:

  • (Jamf::JPackage)

    Create the Jamf::JPackage object for this version and return it



334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 334

def create_jamf_package
  progress "Jamf: Creating Package object '#{jamf_pkg_name}'", log: :info

  # The filename is temporary, and will be replaced when the file is uploaded
  pkg = Jamf::JPackage.create(
    cnx: jamf_cnx,
    packageName: jamf_pkg_name,
    fileName: "#{jamf_pkg_name}.pkg",
    rebootRequired: reboot,
    notes: jamf_package_notes,
    categoryId: jamf_xolo_category_id,
    osRequirements: ">=#{min_os}"
  )

  # TODO: Implement max_os, either here, or by maintaining a smart group?
  # I really wish jamf would improve how package objects handle
  # OS requirements, building in the concept of min/max

  self.jamf_pkg_id = pkg.save
  # save the data now so the pkg_id is available for immeadiate use, e.g. by pkg upload
  save_local_data
  pkg
rescue => e
  msg = "Jamf: Failed to create Jamf::JPackage '#{jamf_pkg_name}': #{e.class}: #{e}"
  log_error msg
  raise Xolo::ServerError, msg
end

#create_jamf_patch_policyJamf::PatchPolicy

Returns The xolo patch policy for this version.

Returns:

  • (Jamf::PatchPolicy)

    The xolo patch policy for this version



935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 935

def create_jamf_patch_policy
  progress "Jamf: Creating Patch Policy for Version '#{version}' of Title '#{title}'.", log: :info

  # TODO: decide how many patch policies - see comments at top
  # Probably one: for pilots initially and then rescoped to all for release
  #
  # TODO: How to set these, and should they be settable
  # at the Xolo::Title or  Xolo::Version level?
  #
  # allow downgrade? No, to start with.
  # When a version is released, IF we are rolling back, then this will be set.
  # This is to be set only on the current release and only when it was a rollback.
  #
  # patch_unknown_versions... yes?
  #
  # if not in ssvc:
  # - grace period?
  # - update warning Message and Subject
  #
  # if in ssvc:
  # - any way to use existing icon?
  # - use title desc... do we want a version desc??
  # - notifications?  Message and Subject? SSvc only, Notif Ctr?
  # - deadline and grace period message and subbject

  ppol = Jamf::PatchPolicy.create(
    cnx: jamf_cnx,
    name: jamf_patch_policy_name,
    patch_title: title_object.jamf_patch_title.id,
    target_version: version
  )

  # when first creating a patch policy, its status is always
  # 'pilot' so the scope targets are the pilot groups, if any.
  # When the version is released, the patch policy will be
  # rescoped to all targets (limited by eligibility)
  set_policy_pilot_groups ppol

  # exclusions are for always
  set_policy_exclusions ppol

  # This will be set to true as needed if
  # a rollback is being done
  ppol.allow_downgrade = false

  # This should always be false, so that
  # we don't accidentally downgrade non-xolo test installs,
  # or server-pushed updates (like with commvault or cisco VPN)
  ppol.patch_unknown = false

  ppol.enable

  ppol.save

  # refetch it rather than using the one we just created
  Jamf::PatchPolicy.fetch(name: jamf_patch_policy_name, cnx: jamf_cnx)
end

#delete_jamf_packagevoid

This method returns an undefined value.

Delete the package for this version from Jamf Pro. Package deletion takes a long time, so we do it in a threadpool and tell the admin to check the Alert Tool for completion (if we have an alert tool in place) or to wait at least 5 min before re-adding the same version.



444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 444

def delete_jamf_package
  pkg_id = Jamf::JPackage.valid_id packageName: jamf_pkg_name, cnx: jamf_cnx
  return unless pkg_id

  msg = "Jamf: Starting deletion of Package '#{jamf_pkg_name}' id #{jamf_pkg_id} at #{Time.now.strftime '%F %T'}"
  progress msg, log: :info

  warning = +"IMPORTANT: Package deletion is slow. If you plan to re-add this version, '#{version}', please\n  "
  warning <<
    if Xolo::Server.config.alert_tool
      'check your Xolo alerts for completion, which can take up to 5 minutes,'
    else
      'wait at least 5 minutes'
    end
  warning << ' before re-adding this version.'

  progress warning, log: nil

  self.class.pkg_deletion_pool.post do
    start = Time.now
    log_info "Jamf: Started threadpool deletion of Package '#{jamf_pkg_name}' id #{jamf_pkg_id} at #{start}"
    jamf_cnx.timeout = 3600
    Jamf::JPackage.delete pkg_id, cnx: jamf_cnx
    finish = Time.now
    duration = (finish - start).to_i.pix_humanize_secs
    log_info "Jamf: Deleted Package '#{jamf_pkg_name}' id #{jamf_pkg_id} in #{duration}", alert: true
  rescue => e
    log_error "Package Deletion thread: #{e.class}: #{e}"
    e.backtrace.each { |l| log_error "..#{l}" }
  end
end

#delete_version_from_jamfvoid

This method returns an undefined value.

Delete an entire version from Jamf Pro This includes the package, the manual install policy, the auto install policy, and the patch policy.



253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 253

def delete_version_from_jamf
  log_debug "Deleting Version '#{version}' from Jamf"

  # The Policies
  pols = [
    jamf_manual_install_policy,
    jamf_auto_install_policy,
    jamf_auto_reinstall_policy,
    jamf_patch_policy
  ]
  pols.each do |pol|
    next unless pol

    progress "Jamf: Deleting #{pol.class} '#{pol.name}'", log: :info
    pol.delete
  end

  # The Installed Group
  if jamf_installed_group
    progress "Jamf: Deleting #{jamf_installed_group.class} '#{jamf_installed_group.name}'", log: :info
    jamf_installed_group.delete
  end

  # Delete package object
  # This is slow and it blocks, so do it in a thread and update progress every
  # 15 secs
  return unless Jamf::JPackage.valid_id packageName: jamf_pkg_name, cnx: jamf_cnx

  delete_jamf_package

  # The code below is used when we want real-time progress updates to xadm
  # while deletion is happening. It's slow, so we're not using it now.

  # msg = "Jamf: Starting deletion of Package '#{jamf_pkg_name}' id #{jamf_pkg_id} at #{Time.now.strftime '%F %T'}..."
  # progress msg, log: :debug

  # # do this in another thread, so we can report the progress while its happening
  # pkg_del_thr = Thread.new { Jamf::JPackage.fetch(packageName: jamf_pkg_name, cnx: jamf_cnx).delete }
  # pkg_del_thr.name = "package-deletion-thread-#{session[:xolo_id]}"
  # sleep 15
  # while pkg_del_thr.alive?
  #   progress "... #{Time.now.strftime '%F %T'} still deleting, this is slow, sorry."
  #   sleep 15
  # end

  # msg = "Jamf: Deleted Package '#{jamf_pkg_name}' id #{jamf_pkg_id} at  #{Time.now.strftime '%F %T'}"
  # progress msg, log: :debug
end

#deploy_via_mdm(targets) ⇒ Hash

Install this version on a one or more computers via MDM.

Parameters:

  • targets (Hash)

    With the following keys

    • computers: [Array<String, Integer>] The computer identifiers to install on. Identifiers are either serial numbers, names, or Jamf IDs.

    • groups: [Array<String, Integer>] The names or ids of computer groups to install on.

Returns:

  • (Hash)

    The results of the install with the following keys

    • removals: [Array<Hash>] { device: <String>, group: <InteStringger>, reason: <String> }

    • queuedCommands: [Array<Hash>] { device: <String>, commandUuid: <String> }

    • errors: [Array<Hash>] { device: <String>, group: <Integer>, reason: <String> }



1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
1414
1415
1416
1417
1418
1419
1420
1421
1422
1423
1424
1425
1426
1427
1428
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439
1440
1441
1442
1443
1444
1445
1446
1447
1448
1449
1450
1451
1452
1453
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1400

def deploy_via_mdm(targets)
  unless dist_pkg
    raise Xolo::UnsupportedError,
          'MDM deployment is not supported for this version, it is not a Distribution Package.'
  end

  all_targets = targets[:computers] || []
  removals = []

  # expand groups into computers,
  all_targets += expand_groups_for_deploy(targets[:groups], removals) if targets[:groups]

  # remove duplicates
  all_targets.uniq!

  # remove invalid computers, after this all_targets will be valid computer ids
  remove_invalid_computers_for_deploy(all_targets, removals)

  # remove members of excluded groups from the list of targets
  remove_exclusions_from_deploy(all_targets, removals)

  if all_targets.empty?
    log_info "Jamf: No valid computers to deploy to for version '#{version}' of title '#{title}'."
    queued_cmds = []
    deploy_errs = []

  else
    # deploy the package to the computers
    jamf_package.deploy_via_mdm computer_ids: all_targets
    # convert ids to names for the response
    comp_ids_to_names = Jamf::Computer.map_all(:id, to: :name, cnx: jamf_cnx)

    queued_cmds = jamf_package.deploy_response[:queuedCommands].map do |qc|
      { device: comp_ids_to_names[qc[:device]], commandUuid: qc[:commandUuid] }
    end

    deploy_errs = jamf_package.deploy_response[:errors].map do |err|
      { device: comp_ids_to_names[err[:device]], reason: err[:reason] }
    end

    log_info "Jamf: Deployed version '#{version}' of title '#{title}' to #{all_targets.size} computers via MDM"

  end

  removals.each { |r| log_info "Jamf: Removal #{r}" }
  queued_cmds.each { |qc| log_info "Jamf: Queued Command #{qc}" }
  deploy_errs.each { |err| log_info "Jamf: Error #{err}" }

  {
    removals: removals,
    queuedCommands: queued_cmds,
    errors: deploy_errs
  }
end

#disable_policies_for_deprecation_or_skipping(reason) ⇒ void

This method returns an undefined value.

Disable the auto-install and patch policies for this version when it is deprecated or skipped

Leave the manual install policy active, but remove it from self-service

Parameters:

  • reason (Symbol)

    :deprecated or :skipped



1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1132

def disable_policies_for_deprecation_or_skipping(reason)
  progress "Jamf: Disabling auto-install policy for #{reason} version '#{version}'"
  pol = jamf_auto_install_policy
  pol.disable
  pol.save

  # don't disable the auto-reinstall policy - it may be needed
  # for any re-uploads of the pkg for this version, even if deprecated/skipped

  progress "Jamf: Disabling patch policy for #{reason} version '#{version}'"
  ppol = jamf_patch_policy
  ppol.disable
  # ensure patch policy is NOT set to 'allow downgrade'
  ppol.allow_downgrade = false
  ppol.save
end

#expand_groups_for_deploy(groups, removals) ⇒ Array<Integer>

expand computer groups given for deploy_via_mdm

Parameters:

  • groups (Array<String, Integer>)

    The names or ids of computer groups to install on.

  • removals (Array<Hash>)

    The groups that are not valid, for reporting back to the caller

Returns:

  • (Array<Integer>)

    The ids of the computers in the groups



1462
1463
1464
1465
1466
1467
1468
1469
1470
1471
1472
1473
1474
1475
1476
1477
1478
1479
1480
1481
1482
1483
1484
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1462

def expand_groups_for_deploy(groups, removals)
  log_debug "Expanding group targets for MDM deployment of title '#{title}',  version '#{version}'"

  computers = []
  groups.each do |g|
    gid = Jamf::ComputerGroup.valid_id g, cnx: jamf_cnx
    if gid
      jgroup = Jamf::ComputerGroup.fetch id: gid, cnx: jamf_cnx

      if excluded_groups_to_use.include? jgroup.name
        log_debug "Jamf: Group '#{jgroup.name}' is in the excluded groups list. Removing."
        removals << { device: nil, group: g, reason: "Group '#{jgroup.name}' is in the excluded groups list" }
        next
      end
      log_debug "Jamf: Adding computers from group '#{jgroup.name}' to deployment targets"
      computers += jgroup.member_ids
    else
      log_debug "Jamf: Group '#{g}' not found in Jamf Pro. Removing."
      removals << { device: nil, group: g, reason: 'Group not found in Jamf Pro' }
    end
  end
  computers
end

#jamf_auto_install_policyJamf::Policy

Create or fetch the auto install policy for this version If we are deleting and it doesn’t exist, return nil.

Returns:

  • (Jamf::Policy)

    The auto-install-policy for this version, if it exists



491
492
493
494
495
496
497
498
499
500
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 491

def jamf_auto_install_policy
  @jamf_auto_install_policy ||=
    if jamf_auto_install_policy_exist?
      Jamf::Policy.fetch(name: jamf_auto_install_policy_name, cnx: jamf_cnx)
    else
      return if deleting?

      create_jamf_auto_install_policy
    end
end

#jamf_auto_install_policy_exist?Boolean

Returns does the jamf_auto_install_policy exist?.

Returns:

  • (Boolean)

    does the jamf_auto_install_policy exist?



482
483
484
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 482

def jamf_auto_install_policy_exist?
  Jamf::Policy.all_names(cnx: jamf_cnx).include? jamf_auto_install_policy_name
end

#jamf_auto_install_policy_urlString

Returns the URL for the Jamf Pro Policy that does auto-installs of this version.

Returns:

  • (String)

    the URL for the Jamf Pro Policy that does auto-installs of this version



565
566
567
568
569
570
571
572
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 565

def jamf_auto_install_policy_url
  return @jamf_auto_install_policy_url if @jamf_auto_install_policy_url

  pol_id = Jamf::Policy.valid_id jamf_auto_install_policy_name, cnx: jamf_cnx
  return unless pol_id

  @jamf_auto_install_policy_url = "#{jamf_gui_url}/policies.html?id=#{pol_id}&o=r"
end

#jamf_auto_reinstall_policyJamf::Policy

Create or fetch the auto re-install policy for this version If we are deleting and it doesn’t exist, return nil.

Returns:

  • (Jamf::Policy)

    The auto-install-policy for this version, if it exists



805
806
807
808
809
810
811
812
813
814
815
816
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 805

def jamf_auto_reinstall_policy
  @jamf_auto_reinstall_policy ||=
    if jamf_auto_reinstall_policy_exist?
      Jamf::Policy.fetch(name: jamf_auto_reinstall_policy_name, cnx: jamf_cnx)
    else
      return if deleting?
      # don't create unless there's been a re-upload of the pkg
      return unless reupload_date

      create_jamf_auto_reinstall_policy
    end
end

#jamf_auto_reinstall_policy_exist?Boolean

Returns does the jamf_auto_reinstall_policy exist?.

Returns:

  • (Boolean)

    does the jamf_auto_reinstall_policy exist?



796
797
798
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 796

def jamf_auto_reinstall_policy_exist?
  Jamf::Policy.all_names(cnx: jamf_cnx).include? jamf_auto_reinstall_policy_name
end

#jamf_auto_reinstall_policy_urlString

Returns the URL for the Jamf Pro Policy that does auto reinstalls of this version.

Returns:

  • (String)

    the URL for the Jamf Pro Policy that does auto reinstalls of this version



864
865
866
867
868
869
870
871
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 864

def jamf_auto_reinstall_policy_url
  return @jamf_auto_reinstall_policy_url if @jamf_auto_reinstall_policy_url

  pol_id = Jamf::Policy.valid_id jamf_auto_reinstall_policy_name, cnx: jamf_cnx
  return unless pol_id

  @jamf_auto_reinstall_policy_url = "#{jamf_gui_url}/policies.html?id=#{pol_id}&o=r"
end

#jamf_gui_urlString

Returns The start of the Jamf Pro URL for GUI/WebApp access.

Returns:

  • (String)

    The start of the Jamf Pro URL for GUI/WebApp access



304
305
306
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 304

def jamf_gui_url
  server_app_instance.jamf_gui_url
end

#jamf_installed_groupJamf::ComputerGroup

Create or fetch the smart group of macs with this version installed If we are deleting and it doesn’t exist, return nil

Returns:

  • (Jamf::ComputerGroup)

    the smart group.



672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 672

def jamf_installed_group
  return @jamf_installed_group if @jamf_installed_group

  if jamf_installed_group_exist?
    @jamf_installed_group = Jamf::ComputerGroup.fetch(
      name: jamf_installed_group_name,
      cnx: jamf_cnx
    )
  else
    return if deleting?
    # don't create unless there's been a re-upload of the pkg
    return unless reupload_date

    create_jamf_installed_group
  end
  @jamf_installed_group
end

#jamf_installed_group_criteriaArray<Jamf::Criteriable::Criterion>

The criteria for the smart group in Jamf that contains all Macs with this version of this title installed

If we have, or are about to update to, a version_script (EA) then use it, otherwise use the app_name and app_bundle_id.

Returns:

  • (Array<Jamf::Criteriable::Criterion>)


738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 738

def jamf_installed_group_criteria
  # does this title use an app bundle?
  if title_object.app_name
    [
      Jamf::Criteriable::Criterion.new(
        and_or: :and,
        name: 'Application Title',
        search_type: 'is',
        value: title_object.app_name
      ),

      Jamf::Criteriable::Criterion.new(
        and_or: :and,
        name: 'Application Bundle ID',
        search_type: 'is',
        value: title_object.app_bundle_id
      ),

      Jamf::Criteriable::Criterion.new(
        and_or: :and,
        name: 'Application Version',
        search_type: 'is',
        value: version
      )
    ]

  # if not, it must have a version script
  elsif title_object.version_script
    [
      Jamf::Criteriable::Criterion.new(
        and_or: :and,
        name: title_object.jamf_normal_ea_name,
        search_type: 'is',
        value: version
      )
    ]

  else
    raise Xolo::Core::Exceptions::InvalidDataError, "Title #{title} has neither a version_script nor a defined app bundle."
  end
end

#jamf_installed_group_exist?Boolean

Returns does the jamf_installed_group exist?.

Returns:

  • (Boolean)

    does the jamf_installed_group exist?



663
664
665
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 663

def jamf_installed_group_exist?
  Jamf::ComputerGroup.all_names(cnx: jamf_cnx).include? jamf_installed_group_name
end

#jamf_installed_group_urlObject



781
782
783
784
785
786
787
788
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 781

def jamf_installed_group_url
  return @jamf_installed_group_url if @jamf_installed_group_url

  gr_id = Jamf::ComputerGroup.valid_id jamf_installed_group_name, cnx: jamf_cnx
  return unless gr_id

  @jamf_installed_group_url = "#{jamf_gui_url}/smartComputerGroups.html?id=#{gr_id}&o=r"
end

#jamf_manual_install_policyJamf::Policy

Create or fetch the manual install policy for this version If we are deleting and it doesn’t exist, return nil.

Returns:

  • (Jamf::Policy)

    The manual-install-policy for this version, if it exists



589
590
591
592
593
594
595
596
597
598
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 589

def jamf_manual_install_policy
  @jamf_manual_install_policy ||=
    if jamf_manual_install_policy_exist?
      Jamf::Policy.fetch(name: jamf_manual_install_policy_name, cnx: jamf_cnx)
    else
      return if deleting?

      create_jamf_manual_install_policy
    end
end

#jamf_manual_install_policy_exist?Boolean

Returns does the jamf_manual_install_policy exist?.

Returns:

  • (Boolean)

    does the jamf_manual_install_policy exist?



580
581
582
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 580

def jamf_manual_install_policy_exist?
  Jamf::Policy.all_names(cnx: jamf_cnx).include? jamf_manual_install_policy_name
end

#jamf_manual_install_policy_urlString

Returns the URL for the Jamf Pro Policy that does manual installs of this version.

Returns:

  • (String)

    the URL for the Jamf Pro Policy that does manual installs of this version



648
649
650
651
652
653
654
655
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 648

def jamf_manual_install_policy_url
  return @jamf_manual_install_policy_url if @jamf_manual_install_policy_url

  pol_id = Jamf::Policy.valid_id jamf_manual_install_policy_name, cnx: jamf_cnx
  return unless pol_id

  @jamf_manual_install_policy_url = "#{jamf_gui_url}/policies.html?id=#{pol_id}&o=r"
end

#jamf_packageJamf::JPackage

Create or fetch the Jamf::JPackage object for this version Returns nil if the package doesn’t exist and we’re deleting

Returns:

  • (Jamf::JPackage)

    the Package object associated with this version



317
318
319
320
321
322
323
324
325
326
327
328
329
330
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 317

def jamf_package
  return @jamf_package if @jamf_package

  id = jamf_pkg_id || Jamf::JPackage.valid_id(name: jamf_pkg_name, cnx: jamf_cnx)
  @jamf_package =
    if id
      log_debug "Jamf: Fetching Jamf::JPackage '#{id}'"
      Jamf::JPackage.fetch id: id, cnx: jamf_cnx
    else
      return if deleting?

      create_jamf_package
    end
end

#jamf_package_notes(ttl_obj: nil) ⇒ String

Returns the ‘notes’ text for the Jamf::JPackage object for this version.

Returns:

  • (String)

    the ‘notes’ text for the Jamf::JPackage object for this version



364
365
366
367
368
369
370
371
372
373
374
375
376
377
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 364

def jamf_package_notes(ttl_obj: nil)
  ttl_obj ||= title_object
  pkg_notes = Xolo::Server::Version::JAMF_PKG_NOTES_PREFIX.sub(
    Xolo::Server::Version::JAMF_PKG_NOTES_VERS_PH,
    version
  )
  pkg_notes.sub!(
    Xolo::Server::Version::JAMF_PKG_NOTES_TITLE_PH,
    title
  )
  desc = ttl_obj.changes_for_update.dig(:description, :new) || ttl_obj.description
  pkg_notes << desc
  pkg_notes
end

#jamf_package_urlString

Returns the URL for the Package that installs this version in Jamf Pro.

Returns:

  • (String)

    the URL for the Package that installs this version in Jamf Pro



425
426
427
428
429
430
431
432
433
434
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 425

def jamf_package_url
  return @jamf_package_url if @jamf_package_url
  return unless jamf_pkg_id

  # the old url
  # @jamf_package_url = "#{jamf_gui_url}/packages.html?id=#{jamf_pkg_id}&o=r"

  @jamf_package_url = "#{jamf_gui_url}/view/settings/computer-management/packages/#{jamf_pkg_id}?tab=general"
  # https://casper.pixar.com:8443/view/settings/computer-management/packages/12042?tab=general
end

#jamf_patch_policyJamf::PatchPolicy?

Fetch or create the patch policy for this version If we are deleting and it doesn’t exist, return nil.

Returns:

  • (Jamf::PatchPolicy, nil)

    The patch policy for this version, if it exists



922
923
924
925
926
927
928
929
930
931
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 922

def jamf_patch_policy
  @jamf_patch_policy ||=
    if jamf_patch_policy_exist?
      Jamf::PatchPolicy.fetch(name: jamf_patch_policy_name, cnx: jamf_cnx)
    else
      return if deleting?

      create_jamf_patch_policy
    end
end

#jamf_patch_policy_exist?Boolean

Returns does the jamf_patch_policy exist?.

Returns:

  • (Boolean)

    does the jamf_patch_policy exist?



914
915
916
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 914

def jamf_patch_policy_exist?
  Jamf::PatchPolicy.all_names(:refresh, cnx: jamf_cnx).include? jamf_patch_policy_name
end

#jamf_patch_policy_urlString

Returns the URL for the Jamf Pro Patch Policy that updates to this version.

Returns:

  • (String)

    the URL for the Jamf Pro Patch Policy that updates to this version



1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1028

def jamf_patch_policy_url
  return @jamf_patch_policy_url if @jamf_patch_policy_url

  title_id = title_object.jamf_patch_title_id

  pol_id = Jamf::PatchPolicy.valid_id jamf_patch_policy_name, cnx: jamf_cnx
  return unless pol_id

  @jamf_manual_install_policy_url = "#{jamf_gui_url}/patchDeployment.html?softwareTitleId=#{title_id}&id=#{pol_id}&o=r"
end

#jamf_patch_versionJamf::PatchTitle::Version

Xolo version

Returns:

  • (Jamf::PatchTitle::Version)

    The Jamf::PatchTitle::Version for this

Raises:

  • (Xolo::NoSuchItemError)


1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1282

def jamf_patch_version
  return @jamf_patch_version if @jamf_patch_version

  # NOTE: in the line below, use the title_object's call to #jamf_patch_title
  # because that will cache the Jamf::PatchTitle instance, and we need to
  # use it to save changes to its Versions.
  # Using the class method won't cache the instance we will need in the
  # future.
  @jamf_patch_version = title_object.jamf_patch_title.versions[version]
  return @jamf_patch_version if @jamf_patch_version

  # TODO: wait for it to appear when adding?
  msg = "Jamf: Version '#{version}' of Title '#{title}' is not visible in Jamf. Is the Patch enabled in the Title Editor?"
  log_error msg
  raise Xolo::NoSuchItemError, msg
end

#patch_reportArrah<Hash>

Get the patch report for this version

Returns:

  • (Arrah<Hash>)

    Data for each computer with this version of this title installed



1380
1381
1382
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1380

def patch_report
  title_object.patch_report vers: version
end

#remove_exclusions_from_deploy(targets, removals) ⇒ void

This method returns an undefined value.

Remove exclusions from the list of targets for deploy_via_mdm

Parameters:

  • targets (Array<Integer>)

    The ids of computers to install on.

  • removals (Array<Hash>)

    The computers that are not valid, for reporting back to the caller



1514
1515
1516
1517
1518
1519
1520
1521
1522
1523
1524
1525
1526
1527
1528
1529
1530
1531
1532
1533
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1514

def remove_exclusions_from_deploy(targets, removals)
  log_debug "Removing excluded computer targets for MDM deployment of title '#{title}',  version '#{version}'"

  excluded_groups_to_use.each do |group|
    gid = Jamf::ComputerGroup.valid_id group, cnx: jamf_cnx
    unless gid
      log_error "Jamf: Excluded group '#{group}' not found in Jamf Pro. Skipping."
      next
    end # unless gid

    jgroup = Jamf::ComputerGroup.fetch id: gid, cnx: jamf_cnx
    jgroup.members.each do |member|
      next unless targets.include? member[:id]

      log_debug "Jamf: Removing computer '#{member[:name]}' (#{member[:id]}) from deployment targets because it is in excluded group '#{group}'"
      targets.delete member[:id]
      removals << { device: member[:name], group: nil, reason: "In excluded group '#{group}'" }
    end
  end # excluded_groups_to_use.each
end

#remove_invalid_computers_for_deploy(targets, removals) ⇒ void

This method returns an undefined value.

remove invalid computers from the list of targets for deploy_via_mdm

Parameters:

  • targets (Array<String, Integer>)

    The names or ids of computers to install on.

  • removals (Array<Hash>)

    The computers that are not valid, for reporting back to the caller



1493
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1493

def remove_invalid_computers_for_deploy(targets, removals)
  log_debug "Removing invalid computer targets for MDM deployment of title '#{title}',  version '#{version}'"

  targets.map! do |c|
    id = Jamf::Computer.valid_id c, cnx: jamf_cnx
    if id
      id
    else
      removals << { device: c, group: nil, reason: 'Computer not found in Jamf Pro' }
      nil
    end
  end.compact!
end

#repair_jamf_auto_install_policyObject

repair the auto-install policy only



523
524
525
526
527
528
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 523

def repair_jamf_auto_install_policy
  progress "Jamf: Repairing Auto Install Policy '#{jamf_auto_install_policy_name}'", log: :info
  pol = jamf_auto_install_policy
  configure_jamf_auto_install_policy(pol)
  pol.save
end

#repair_jamf_auto_reinstall_policyObject

Reset the configuration of the jamf_installed_group



831
832
833
834
835
836
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 831

def repair_jamf_auto_reinstall_policy
  return unless reupload_date

  progress "Jamf: Repairing Auto Re-Install Policy: #{jamf_auto_reinstall_policy_name}", log: :debug
  configure_jamf_auto_reinstall_policy jamf_auto_reinstall_policy
end

#repair_jamf_installed_groupObject

Reset the configuration of the jamf_installed_group but only if there’s been a re-upload of the pkg



710
711
712
713
714
715
716
717
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 710

def repair_jamf_installed_group
  return unless reupload_date

  progress "Jamf: Repairing smart group '#{jamf_installed_group_name}'", log: :info

  configure_jamf_installed_group jamf_installed_group
  jamf_installed_group.save
end

#repair_jamf_manual_install_policyObject

repair the manual-install policy only



617
618
619
620
621
622
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 617

def repair_jamf_manual_install_policy
  pol = jamf_manual_install_policy
  progress "Jamf: Repairing Manual Install Policy '#{jamf_manual_install_policy_name}'", log: :info
  configure_jamf_manual_install_policy(pol)
  pol.save
end

#repair_jamf_packageObject

repair the package object only



411
412
413
414
415
416
417
418
419
420
421
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 411

def repair_jamf_package
  # If these values are all correct, nothing will be saved
  progress "Jamf: Repairing Package '#{jamf_pkg_name}'", log: :info
  jamf_package.packageName = jamf_pkg_name
  jamf_package.fileName = "#{jamf_pkg_name}.pkg"
  jamf_package.rebootRequired = reboot
  jamf_package.notes = jamf_package_notes
  jamf_package.categoryId = jamf_xolo_category_id
  jamf_package.osRequirements = ">=#{min_os}"
  jamf_package.save
end

#repair_jamf_patch_policyObject

repair the patch policy only



995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 995

def repair_jamf_patch_policy
  progress "Jamf: Repairing Patch Policy '#{jamf_patch_policy_name}'", log: :info
  assign_pkg_to_patch_in_jamf

  ppol = jamf_patch_policy
  ppol.name = jamf_patch_policy_name
  ppol.target_version = version

  # This should always be false, so that
  # we don't accidentally downgrade non-xolo test installs,
  # or server-pushed updates (like with commvault or cisco VPN)
  ppol.patch_unknown = false

  if pilot?
    set_policy_pilot_groups ppol
  else
    ppol.scope.set_all_targets
  end

  # exclusions are for always
  set_policy_exclusions ppol

  if pilot? || released?
    ppol.enable
  else
    ppol.disable
  end

  ppol.save
end

#repair_jamf_version_objectsObject

Validate and fix any Jamf::JPackage objects that related to this version:

  • the package object

  • the installed-group

  • the auto-install policy

  • the manual-install policy

  • the auto-reinstall policy

  • the patch policy



237
238
239
240
241
242
243
244
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 237

def repair_jamf_version_objects
  repair_jamf_package
  repair_jamf_installed_group # wont happen if no reupload_date
  repair_jamf_auto_install_policy
  repair_jamf_manual_install_policy
  repair_jamf_auto_reinstall_policy # wont happen if no reupload_date
  repair_jamf_patch_policy
end

#reset_policies_to_pilotvoid

This method returns an undefined value.

reset all the policies for this version to pilot



1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1153

def reset_policies_to_pilot
  # set scope targets of auto-install policy to pilot-groups and re-enable
  msg = "Jamf: Version '#{version}': Setting scope targets of auto-install policy to pilot_groups: #{pilot_groups_to_use.join(', ')}"
  progress msg, log: :info

  jamf_auto_install_policy.scope.set_targets :computer_groups, pilot_groups_to_use
  jamf_auto_install_policy.enable
  jamf_auto_install_policy.save

  msg = "Jamf: Version '#{version}': Setting scope targets of patch policy to pilot_groups"
  progress msg, log: :info

  # set scope targets of patch policy to pilot-groups and re-enable
  jamf_patch_policy.scope.set_targets :computer_groups, pilot_groups_to_use
  # ensure patch policy is NOT set to 'allow downgrade'
  jamf_patch_policy.allow_downgrade = false
  jamf_patch_policy.enable
  jamf_patch_policy.save
end

#set_policy_exclusions(pol, ttl_obj: nil) ⇒ Object

set excluded groups in a [patch] policy object’s scope REMEMBER TO SAVE THE POLICY LATER

This applies more nuance to the ‘excluded_groups_to_use’ depending on the policy in question. E.g. manual-install policy should not have the installed-group excluded, to allow re-installs

Parameters:

  • pol (Jamf::Policy, Jamf::PatchPolicy)
  • ttl_obj (Xolo::Server::Title) (defaults to: nil)

    The pre-instantiated title for ths version. if nil, we’ll instantiate it now



1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1100

def set_policy_exclusions(pol, ttl_obj: nil)
  ttl_obj ||= title_object
  # dup, so when we add the installed group below, we don't
  # keep that for future calls to this method.
  exclusions = excluded_groups_to_use(ttl_obj: ttl_obj).dup
  exclusions ||= []

  # the initial auto-install policies must also exclude any mac with the title
  # already installed
  #
  # But the manual-install policy and the auto-reinstall should never exclude it - so that
  # it can be manually installed or automatically re-installed whenever needed
  if pol.is_a?(Jamf::Policy) && pol.name == jamf_auto_install_policy_name
    # calling ttl_obj.jamf_installed_group will create the group if needed
    exclusions << ttl_obj.jamf_installed_group_name
  end

  log_debug "Jamf: updating exclusions for #{pol.class} '#{pol.name}' to: #{exclusions.join ', '}"

  exclusions.uniq!
  pol.scope.set_exclusions :computer_groups, exclusions
end

#set_policy_pilot_groups(pol) ⇒ void

This method returns an undefined value.

set target groups in a pilot [patch] policy object’s scope REMEMBER TO SAVE THE POLICY LATER

Parameters:

  • pol (Jamf::Policy, Jamf::PatchPolicy)


1049
1050
1051
1052
1053
1054
1055
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1049

def set_policy_pilot_groups(pol)
  pilots = pilot_groups_to_use
  pilots ||= []
  log_debug "Jamf: setting pilot scope targets for #{pol.class} '#{pol.name}' to: #{pilots.join ', '}"

  pol.scope.set_targets :computer_groups, pilots
end

#set_policy_release_groups(pol, ttl_obj: nil) ⇒ void

This method returns an undefined value.

set target groups in a non=pilot [patch] policy object’s scope REMEMBER TO SAVE THE POLICY LATER

Parameters:

  • pol (Jamf::Policy, Jamf::PatchPolicy)
  • ttl_obj (Xolo::Server::Title) (defaults to: nil)

    The pre-instantiated title for ths version. if nil, we’ll instantiate it now



1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1076

def set_policy_release_groups(pol, ttl_obj: nil)
  ttl_obj ||= title_object
  targets = release_groups_to_use(ttl_obj: ttl_obj) || []

  log_debug "Jamf: setting release scope targets for #{pol.class} '#{pol.name}' to: #{targets.join ', '}"

  if targets.include? Xolo::TARGET_ALL
    pol.scope.set_all_targets
  else
    pol.scope.set_targets :computer_groups, targets
  end
end

#set_policy_to_all_targets(pol) ⇒ void

This method returns an undefined value.

Set a policy to be scoped to all targets REMEMBER TO SAVE THE POLICY LATER

Parameters:

  • pol (Jamf::Policy, Jamf::PatchPolicy)


1063
1064
1065
1066
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1063

def set_policy_to_all_targets(pol)
  log_debug "Jamf: setting scope target for #{pol.class} '#{pol.name}' to all computers"
  pol.scope.set_all_targets
end

#update_excluded_groups(ttl_obj: nil) ⇒ Object

Update all the excluded_groups policy scopes for this version when either the title or version has changed them

Applies regardless of status

Parameters:

  • ttl_obj (Xolo::Server::Title) (defaults to: nil)

    The pre-instantiated title for ths version. if nil, we’ll instantiate it now



1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1237

def update_excluded_groups(ttl_obj: nil)
  log_debug "Updating Excluded Groups for Version '#{version}' of Title '#{title}'"

  # - update the manual install policy
  pol = jamf_manual_install_policy
  if pol
    progress "Jamf: Updating excluded groups for Manual Install Policy '#{jamf_auto_install_policy_name}'."
    set_policy_exclusions(pol, ttl_obj: ttl_obj)
    pol.save
  end

  # - update the auto install policy
  pol = jamf_auto_install_policy
  if pol
    progress "Jamf: Updating excluded groups for Auto Install Policy '#{jamf_auto_install_policy_name}'."
    set_policy_exclusions(pol, ttl_obj: ttl_obj)
    pol.save
  end

  # - update the auto reinstall policy, but only if it exists
  if jamf_auto_reinstall_policy_exist?
    pol = jamf_auto_reinstall_policy
    if pol
      progress "Jamf: Updating excluded groups for Auto ReInstall Policy '#{jamf_auto_reinstall_policy_name}'."
      set_policy_exclusions(pol, ttl_obj: ttl_obj)
      pol.save
    end
  end

  # - update the patch policy
  pol = jamf_patch_policy
  return unless pol

  progress "Jamf: Updating exccluded groups for Patch Policy '#{jamf_patch_policy_name}'."
  set_policy_exclusions(pol, ttl_obj: ttl_obj)
  pol.save
end

#update_jamf_package_notes(ttl_obj: nil) ⇒ void

This method returns an undefined value.

update the description for the Jamf::JPackage



381
382
383
384
385
386
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 381

def update_jamf_package_notes(ttl_obj: nil)
  ttl_obj ||= title_object
  progress "Jamf: Updating notes for Jamf::JPackage '#{jamf_pkg_name}'", log: :debug
  jamf_package.notes = jamf_package_notes(ttl_obj: ttl_obj)
  jamf_package.save
end

#update_jamf_pkg_min_osvoid

This method returns an undefined value.

update the min_os setting for the Jamf::JPackage



401
402
403
404
405
406
407
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 401

def update_jamf_pkg_min_os
  new_min = changes_for_update&.key?(:min_os) ? changes_for_update[:min_os][:new] : min_os
  progress "Jamf: Updating os_requirement for Jamf::JPackage '#{jamf_pkg_name}' to '#{new_min}'",
           log: :debug
  jamf_package.osRequirements = ">=#{new_min}"
  jamf_package.save
end

#update_jamf_pkg_rebootvoid

This method returns an undefined value.

update the reboot setting for the Jamf::JPackage



391
392
393
394
395
396
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 391

def update_jamf_pkg_reboot
  new_reboot = changes_for_update&.key?(:reboot) ? changes_for_update[:reboot][:new] : reboot
  progress "Jamf: Updating reboot setting for Jamf::JPackage '#{jamf_pkg_name}' to '#{new_reboot}'", log: :debug
  jamf_package.rebootRequired = new_reboot
  jamf_package.save
end

#update_pilot_groupsObject

Update all the pilot_groups policy scopes for this version when either the title or version has changed them

Nothing to do if the version isn’t currently in :pilot status

Parameters:

  • ttl_obj (Xolo::Server::Title)

    The pre-instantiated title for ths version. if nil, we’ll instantiate it now



1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1181

def update_pilot_groups
  # nothing unless we're in pilot
  return unless status == Xolo::Server::Version::STATUS_PILOT

  # - no changes to the manual install policy: scope-target is all

  # - update the auto install policy
  progress "Jamf: Updating pilot groups for Auto Install Policy '#{jamf_auto_install_policy_name}'."

  pol = jamf_auto_install_policy

  set_policy_pilot_groups(pol)
  pol.save

  # - update the patch policy
  progress "Jamf: Updating pilot groups for Patch Policy '#{jamf_patch_policy_name}'."

  pol = jamf_patch_policy

  set_policy_pilot_groups(pol)
  pol.save
end

#update_release_groups(ttl_obj: nil) ⇒ Object

Update all the release_groups policy scopes for this version when either the title or version has changed them

Nothing to do if the version is currently in pending or pilot status

Parameters:

  • ttl_obj (Xolo::Server::Title) (defaults to: nil)

    The pre-instantiated title for ths version. if nil, we’ll instantiate it now



1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 1212

def update_release_groups(ttl_obj: nil)
  return unless status == Xolo::Server::Version::STATUS_RELEASED

  # - no changes to the manual install policy: scope-target is all

  # - update the auto-install policy
  pol = jamf_auto_install_policy
  return unless pol

  set_policy_release_groups(pol, ttl_obj: ttl_obj)
  pol.save
  progress "Jamf: updated release groups for Auto Install Policy '#{jamf_auto_install_policy_name}'.",
           log: :info

  # - no changes to the patch policy: scope-target is all once released
end

#update_version_in_jamfObject

Apply edits to the Xolo version to Jamf as needed This includes scope changes in policies, changes to pkg ‘reboot’ setting and changes to pkg ‘os_requirements’ Uploading a new .pkg installer happen separately



208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 208

def update_version_in_jamf
  update_pilot_groups if changes_for_update&.key? :pilot_groups
  update_release_groups(ttl_obj: title_object) if changes_for_update&.key? :release_groups
  update_excluded_groups(ttl_obj: title_object) if changes_for_update&.key? :excluded_groups

  update_jamf_pkg_reboot if changes_for_update&.key? :reboot
  update_jamf_pkg_min_os if changes_for_update&.key? :min_os

  # TODO: Update the critera for the jamf_installed_group IF
  #
  # - the group exists AND
  # - the title has changed how it determines installed versions, e.g. by adding or
  #   changing a version_script or app_bundle_id
  #   Changing those is very rare, and ill-advised, so we will implement
  #   this later.
  #
  # if jamf_installed_group_exist?
  # end
end

#wait_to_enable_reinstall_policyvoid

This method returns an undefined value.

This will start a thread that will wait some period of time (to allow for pkg uploads to complete) before enabling and flushing the logs for the reinstall policy. This will make all macs with this version installed get it re-installed.



878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
# File 'lib/xolo/server/mixins/version_jamf_access.rb', line 878

def wait_to_enable_reinstall_policy
  return if @enable_reinstall_policy_thread&.alive?
  return unless reupload_date

  # TODO: some setting to determine how long to wait?
  # - If uploading via the Jamf API, we need to give it time
  #   to then upload the file to the cloud distribution point
  # - If uploading via a custom tool, we need to give that
  #   tool time to re-upload to wherever it uploads to
  # - May need to wait for other non-jamf/non-xolo processes
  #   to sync the package to other distribution points. This
  #   might be very site-specific.

  # For now, we wait 15 minutes.
  wait_time = JAMF_AUTO_REINSTALL_WAIT_SECS

  @enable_reinstall_policy_thread = Thread.new do
    log_debug "Jamf: Starting enable_reinstall_policy_thread: waiting #{wait_time} seconds before enabling reinstall policy for version #{version} of title #{title}"
    sleep wait_time

    log_debug "Jamf: enable_reinstall_policy_thread: enabling and flushing logs for reinstall policy for version #{version} of title #{title}"

    pol = jamf_auto_reinstall_policy
    pol.enable
    pol.flush_logs
    pol.save
  end
  @enable_reinstall_policy_thread.name = "enable_reinstall_policy_thread-#{title}-#{version}"
end