xolo-server 2.5.0 → 2.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7f515836aab0143c5343395e240de91947be9aef7cc70b266d4e1a84eb5fe714
4
- data.tar.gz: 7f438c26d4974cb273241ec6bd72a9521eef562283cea9f64ba5f4521c34cf40
3
+ metadata.gz: 584212a83456feefa7f2a08d3f1522093515767e5ca1e61a00335d0141c370fe
4
+ data.tar.gz: 0b73315cb10ee4b87d476ebba60ca3021a5d81080175d9b954bef88daaee047a
5
5
  SHA512:
6
- metadata.gz: 2b2cc84027b9a9af0fc4619d1ba5d564700043207e5ee96be50a69f248b5b4644605b5de569cb9906ec6b71c3d7ee322041bfe4395187cdcce06bcacf9b2d099
7
- data.tar.gz: 344224658c124b01d6caa0b175ef64e3e200618335224119efb2d5430a38e178d15bba1878282ee16908c51c9979d5dbadbcd02da8aa293812ac22a1a4d32598
6
+ metadata.gz: f3fdc24942ff7f08bbe1205c19823359be852cc240f3ab818ea6b44a59d7c7fdeb3a207527d26a20dd4d9e2eab1fd5fd9547e93350be1c14c7e5f6d6b4eee3e1
7
+ data.tar.gz: f800c804e3fe669a99f4e51e2a36e8a5dd3393479094387f8998bec0c9d4ed320a2f7486569f31225f60823722835dd4854cf5d7be4f2ee6a30376eb6f30af4d
@@ -726,6 +726,25 @@ module Xolo
726
726
  ENDDESC
727
727
  },
728
728
 
729
+ # @!attribute deprecated_lifetime
730
+ # @return [Integer] How many days after deprecation before a version is automatically deleted from Xolo?
731
+ #
732
+ deprecated_lifetime: {
733
+ label: 'Deprecated Lifetime',
734
+ cli: :L,
735
+ validate: true,
736
+ type: :string,
737
+ changelog: true,
738
+ invalid_msg: "Invalid value. Must be a positive integer or 'none'",
739
+ desc: <<~ENDDESC
740
+ When a version is deprecated, it will be automatically deleted by the nightly maintenance this many days later. If set to 'none', deprecated versions will be auto-deleted based on the Xolo server settings.
741
+
742
+ Deprecated versions are those that have been released, but a newer version has been released since then.
743
+
744
+ This setting is especially useful for titles that have frequent versions, to avoid cluttering the xolo and Jamf servers with old versions.
745
+ ENDDESC
746
+ },
747
+
729
748
  # @!attribute self_service
730
749
  # @return [Boolean] Does this title appear in Self Service?
731
750
  self_service: {
@@ -12,7 +12,7 @@ module Xolo
12
12
 
13
13
  module Version
14
14
 
15
- VERSION = '2.5.0'.freeze
15
+ VERSION = '2.6.0'.freeze
16
16
 
17
17
  end
18
18
 
@@ -44,11 +44,16 @@ module Xolo
44
44
  PROGRESS_COMPLETE = 'PROGRESS_COMPLETE'
45
45
 
46
46
  # The max time (in seconds) to wait for a the Jamf server to
47
- # see a change in the Title Editor, e.g.
48
- # a new version appearing or an EA needing acceptance.
47
+ # see a change in the Title Editor, e.g. an EA needing acceptance.
49
48
  # Normally the Jamf server will check in with the Title Editor
50
49
  # every 5 minutes.
51
- MAX_JAMF_WAIT_FOR_TITLE_EDITOR = 3600
50
+ #
51
+ # TEMPORARY: Checks for new versions/patches and Patch EAs happen
52
+ # over 9+ hours.
53
+ # See the method activate_managed_patch_version_in_jamf in
54
+ # version_jamf_access.rb
55
+ # and method auto_accept_patch_ea_in_thread in title_jamf_access.rb.
56
+ MAX_JAMF_WAIT_FOR_TITLE_EDITOR = 3600 * 9
52
57
 
53
58
  # The max time (in seconds) to wait for a the Jamf server to
54
59
  # stop the pkg deletion thread pool. It will wait until the
@@ -457,7 +457,7 @@ module Xolo
457
457
  title_objects.each do |title_obj|
458
458
  title_obj.version_objects.each do |version|
459
459
  if version.deprecated?
460
- cleanup_deprecated_version version
460
+ cleanup_deprecated_version title_obj, version
461
461
  elsif version.skipped?
462
462
  cleanup_skipped_version version
463
463
  end # case
@@ -470,13 +470,21 @@ module Xolo
470
470
  # @param version [Xolo::Server::Version] the version to cleanup
471
471
  # @return [void]
472
472
  ################################
473
- def cleanup_deprecated_version(version)
474
- # do nothing if the deprecated_lifetime_days is 0 or less
475
- return unless deprecated_lifetime_days.positive?
473
+ def cleanup_deprecated_version(title_obj, version)
474
+ # does this version's title have a custom deprecated lifetime?
475
+ # title_obj.deprecated_lifetime should be a positive integer or nil
476
+ # if nil, use the server's setting
477
+ deprecated_lifetime_to_use = title_obj.deprecated_lifetime || server_deprecated_lifetime_days
478
+
479
+ # do nothing if the deprecated_lifetime_to_use is 0 or less
480
+ # which will only come from the server.
481
+ return unless deprecated_lifetime_to_use.positive?
482
+
483
+ # deprecation_lifetime_to_use is now a positive integer
476
484
 
477
485
  # how many days has this version been deprecated?
478
486
  days_deprecated = (Time.now - version.deprecation_date) / 86_400
479
- return unless days_deprecated > deprecated_lifetime_days
487
+ return unless days_deprecated > deprecated_lifetime_to_use
480
488
 
481
489
  log_info "Maint: Deleting deprecated version '#{version.version}' of title '#{version.title}'"
482
490
  version.delete
@@ -538,8 +546,8 @@ module Xolo
538
546
  # how many days can a version be deprecated?
539
547
  # @return [Integer] the number of days a version can be deprecated
540
548
  ################################
541
- def deprecated_lifetime_days
542
- @deprecated_lifetime_days ||= Xolo::Server.config.deprecated_lifetime_days || DFT_DEPRECATED_LIFETIME_DAYS
549
+ def server_deprecated_lifetime_days
550
+ @server_deprecated_lifetime_days ||= Xolo::Server.config.deprecated_lifetime_days || DFT_DEPRECATED_LIFETIME_DAYS
543
551
  end
544
552
 
545
553
  # Notify the admins about unreleased pilots when the newest one is older than
@@ -418,8 +418,21 @@ module Xolo
418
418
  auto_accept_patch_ea_in_thread
419
419
  end
420
420
 
421
- # Wait for up to an hour for Jamf to notice that our TEd EA needs to be
422
- # accepted, and then do it
421
+ # Wait for up to 9 hours for Jamf to notice that our TEd EA needs to be
422
+ # accepted, and then do it.
423
+ #
424
+ # Normally we'd wait only 1 hour (Xolo::Server::MAX_JAMF_WAIT_FOR_TITLE_EDITOR)
425
+ # But Jamf Cloud instances have a bug where sometimes they'll stop being
426
+ # able to talk to Patch Sources for many hours.
427
+ #
428
+ # We start by checking every 30 seconds
429
+ # After 10 min we check every 2 minutes
430
+ # After an hour, we check every 5 minutes
431
+ # After 3 hours we check every 15 minutes
432
+ #
433
+ # The activate_managed_patch_version_in_jamf method (in version_jamf_access.rb)
434
+ # has also been modified to wait up to 9+hrs.
435
+ #
423
436
  #####################
424
437
  def auto_accept_patch_ea_in_thread
425
438
  # don't do this if there's already one running for this instance
@@ -438,20 +451,52 @@ module Xolo
438
451
  start_time = start_time.strftime '%F %T'
439
452
  did_it = false
440
453
 
441
- while Time.now < max_time
442
- sleep 30
454
+ # start at 30 secs
455
+ sleep_time = 30
456
+ loop_start = Time.now
457
+
458
+ while loop_start < max_time
459
+ sleep sleep_time
443
460
 
444
461
  # refresh our jamf connection cuz it might expire if this takes a while, esp if using
445
462
  # an APIClient
446
463
  jamf_cnx(refresh: true) if jamf_cnx.token.secs_remaining < 90
447
464
 
448
465
  log_debug "Jamf: checking for expected (re)acceptance of version-script ExtensionAttribute '#{ted_ea_key}' since #{start_time}"
449
- next unless jamf_patch_ea_awaiting_acceptance?
450
466
 
451
- accept_jamf_patch_ea_via_api
452
- log_info "Jamf: Auto-accepted use of version-script ExtensionAttribute '#{ted_ea_key}'"
453
- did_it = true
454
- break
467
+ if jamf_patch_ea_awaiting_acceptance?
468
+ accept_jamf_patch_ea_via_api
469
+ log_info "Jamf: Auto-accepted use of version-script ExtensionAttribute '#{ted_ea_key}'"
470
+ did_it = true
471
+ break
472
+
473
+ end # if jamf_patch_ea_awaiting_acceptance?
474
+
475
+ # prep for the next loop
476
+ loop_start = Time.now
477
+ waiting_time = loop_start - start_time
478
+
479
+ sleep_time =
480
+ # if we've been waiting 10 min or less,
481
+ # sleep 30 secs between checks
482
+ if waiting_time <= 600
483
+ 30
484
+
485
+ # if we've been waiting an hour or less
486
+ # sleep 2 min between checks
487
+ elsif waiting_time <= 3600
488
+ 120
489
+
490
+ # if we've been waiting 3 hours or less
491
+ # sleep 5 min between checks
492
+ elsif waiting_time <= 10_800
493
+ 300
494
+
495
+ # if longer than 3 hours, sleep 15 min between checks
496
+ else
497
+ 900
498
+ end # sleep_time = if waiting_time
499
+
455
500
  end # while
456
501
 
457
502
  unless did_it
@@ -315,11 +315,14 @@ module Xolo
315
315
  # The key is jamf_obj_name_pfx on the title
316
316
  # so for title 'foobar', it is 'xolo-foobar' or 'xolotest-foobar' for test servers
317
317
  # That value is also used as the display name
318
- # @return [String] The key and display name of a version script stored
319
- # in the title editor as the ExtAttr for this title
318
+ #
319
+ # @return [String, nil] The key and display name of a version script stored
320
+ # in the title editor as the ExtAttr for this title, IF the title uses an ExtAttr
320
321
  #####################
321
322
  def ted_ea_key
322
- @ted_ea_key ||= "#{jamf_obj_name_pfx_base}#{title}"
323
+ return @ted_ea_key if defined? @ted_ea_key
324
+
325
+ @ted_ea_key = version_script.pix_empty? ? nil : "#{jamf_obj_name_pfx_base}#{title}"
323
326
  end
324
327
 
325
328
  # Create the EA in the Title Editor
@@ -566,11 +569,26 @@ module Xolo
566
569
  # we've already done the known version objects, above
567
570
  next if version_order.include? ted_patch.version
568
571
 
572
+ # progress "DEBUG: app_name: #{app_name}... app_bundle_id: #{app_bundle_id}.... ted_ea_key: #{ted_ea_key}", log: :debug
573
+ # progress "DEBUG: version_script: #{version_script}", log: :debug
574
+
575
+ # ea_name/ted_ea_key was getting passed
576
+ # even when no ea was used, causing windoo errors.
577
+ if app_name
578
+ aname = app_name
579
+ aid = app_bundle_id
580
+ ea_name = nil
581
+ else
582
+ aname = nil
583
+ aid = nil
584
+ ea_name = ted_ea_key
585
+ end
586
+
569
587
  Xolo::Server::Helpers::TitleEditor.set_patch_component_criteria(
570
588
  ted_patch,
571
- app_name: app_name,
572
- app_bundle_id: app_bundle_id,
573
- ea_name: ted_ea_key
589
+ app_name: aname,
590
+ app_bundle_id: aid,
591
+ ea_name: ea_name
574
592
  )
575
593
  ted_patch.enable
576
594
  end
@@ -356,6 +356,9 @@ module Xolo
356
356
  self.jamf_pkg_id = pkg.save
357
357
  # save the data now so the pkg_id is available for immeadiate use, e.g. by pkg upload
358
358
  save_local_data
359
+ log_debug 'TEMP: Pausing 65 secs for server cluster to see new pkg'
360
+ sleep 65
361
+
359
362
  pkg
360
363
  rescue => e
361
364
  msg = "Jamf: Failed to create Jamf::JPackage '#{jamf_pkg_name}': #{e.class}: #{e}"
@@ -1378,11 +1381,29 @@ module Xolo
1378
1381
  raise Xolo::NoSuchItemError, msg
1379
1382
  end
1380
1383
 
1381
- # Wait until the version is visible from the title editor
1382
- # then assign the pkg to it in Jamf Patch,
1383
- # and create the patch policy.
1384
+ # Pkg assignment and patch pol. creation cannot happen until the version
1385
+ # becomes visible from the Title Editor.
1386
+ #
1387
+ # This method starts a thread that waits until then, then assigns the pkg to it
1388
+ # in Jamf Patch, and creates the patch policy.
1389
+ #
1390
+ # Normally Jamf Pro will poll its Patch Sources every 5 minutes, so it _shouldn't_
1391
+ # take more than that for a new version to appear.
1392
+ # But sometime, esp. in Jamf Cloud instances, it may be hours before the version
1393
+ # shows up.
1394
+ #
1395
+ # To deal with this, we check to see if it has appeared every minute for the first 10 min.
1396
+ #
1397
+ # If it hasn't happened by then, we send a notification that we're still waiting
1398
+ # and will check every 10 min for the next 3 hrs.
1399
+ #
1400
+ # If still nothing, send another notification that we'll check every 30 min for
1401
+ # the next 6 hrs
1402
+ #
1403
+ # If still nothing after 9hrs and 10 min, send a final notification that we
1404
+ # are giving up, and please investigate manually. Once Jamf actually sees the version
1405
+ # from the title editor,
1384
1406
  #
1385
- # Do this in a thread so the xadm user doesn't wait up to ?? minutes.
1386
1407
  #
1387
1408
  # @return [void]
1388
1409
  #########################
@@ -1399,36 +1420,80 @@ module Xolo
1399
1420
  @activate_patch_version_thread = Thread.new do
1400
1421
  log_debug "Jamf: Starting activate_patch_version_thread waiting for version #{version} of title #{title} to become visible from the title editor"
1401
1422
 
1402
- start_time = Time.now
1403
- max_time = start_time + Xolo::Server::MAX_JAMF_WAIT_FOR_TITLE_EDITOR
1404
- start_time = start_time.strftime '%F %T'
1405
-
1406
- did_it = false
1423
+ start_time = Time.now.strftime '%F %T'
1424
+ version_visible = false
1407
1425
 
1408
- while Time.now < max_time
1409
- sleep 15
1410
- log_debug "Jamf: checking for version #{version} of title #{title} to become visible from the title editor since #{start_time}"
1426
+ # Check every minute for the first 10 minutes
1427
+ #####
1428
+ 10.times do
1429
+ sleep 60
1430
+ log_debug "Jamf: checking for version #{version} of title #{title} to become visible from the Title Editor since #{start_time}"
1431
+ next unless patch_version_visible_in_jamf?(title_object, version)
1411
1432
 
1412
- # check for the existence of the jamf_patch_title every time, since it might have gone away
1413
- # if the title was deleted while this was happening.
1414
- next unless title_object.jamf_patch_title(refresh: true) && title_object.jamf_patch_title.versions.key?(version)
1415
-
1416
- did_it = true
1433
+ version_visible = true
1417
1434
  break
1435
+ end # 10 times
1436
+
1437
+ # warn, and then check every 10 min for the next 3 hours
1438
+ #####
1439
+ unless version_visible
1440
+ msg = "Jamf: Version '#{version}' of title '#{title}' is still NOT visible from the Title Editor since #{start_time}. Will check every 10 minutes for the next 3 hours."
1441
+ log_warn msg, alert: true
1442
+
1443
+ # every 10 min for 3 hrs = 18 times
1444
+ 18.times do
1445
+ sleep 600
1446
+ log_debug "Jamf: Still checking for version #{version} of title #{title} to become visible from the Title Editor since #{start_time}"
1447
+ next unless patch_version_visible_in_jamf?(title_object, version)
1448
+
1449
+ version_visible = true
1450
+ break
1451
+ end # 18 times
1452
+ end
1453
+
1454
+ # warn, and then check every 30 min for the next 6 hours
1455
+ #####
1456
+ unless version_visible
1457
+ msg = "Jamf: Version '#{version}' of title '#{title}' is STILL NOT visible from the Title Editor since #{start_time}. Will check every 30 minutes for the next 6 hours before giving up."
1458
+ log_warn msg, alert: true
1459
+
1460
+ # every 30 min for 6 hrs = 12 times
1461
+ 12.times do
1462
+ sleep 1800
1463
+ log_debug "Jamf: STILL checking for version #{version} of title #{title} to become visible from the Title Editor since #{start_time}"
1464
+ next unless patch_version_visible_in_jamf?(title_object, version)
1465
+
1466
+ version_visible = true
1467
+ break
1468
+ end # 12 times
1418
1469
  end
1419
1470
 
1420
- if did_it
1471
+ #### did we do it?
1472
+ if version_visible
1421
1473
  activate_patch_version_in_jamf
1422
1474
  msg = "Jamf: Version '#{version}' of title '#{title}' is now visible in Jamf Pro. Package assigned and Patch policy created."
1423
1475
  log_info msg, alert: true
1424
1476
  else
1425
- 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."
1477
+ msg = "Jamf: ERROR: Version '#{version}' of title '#{title}' has not become visible from the Title Editor in over 9 hours. The package has not been assigned, and no patch policy was created. When the version appears in Jamf Patch, run \"xadm repair #{title} '#{version}'\" to assign the pkg and create the patch policy."
1426
1478
  log_error msg, alert: true
1427
1479
  end
1480
+ rescue => e
1481
+ msg = "Error in thread while waiting for version '#{version}' of title '#{title}' to appear from the Title Editor: #{e.class}: #{e}"
1482
+ log_error msg, alert: true
1483
+ e.backtrace.each { |l| log_error "...#{l}" }
1428
1484
  end # thread
1485
+
1429
1486
  @activate_patch_version_thread.name = "activate_patch_version_thread-#{title}-#{version}"
1430
1487
  end
1431
1488
 
1489
+ # @return [Boolean] is a given version/patch of a title visible in Jamf Patch from
1490
+ # its patch source?
1491
+ #################################
1492
+ def patch_version_visible_in_jamf?(title_object, version)
1493
+ title_object.jamf_patch_title(refresh: true) && \
1494
+ title_object.jamf_patch_title.versions.key?(version)
1495
+ end
1496
+
1432
1497
  # Patches for subscribed titles are already visible in Jamf Patch Management
1433
1498
  # So we just need to assign the pkg to the patch version, and create the patch policy.
1434
1499
  ##########################
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xolo-server
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Chris Lasell
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2026-10-23 00:00:00.000000000 Z
11
+ date: 2026-11-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday