xolo-admin 2.3.0 → 2.5.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: 93b88b4836493ad597c2417b6c83f5ed5526a71e1b434ef391ccfe3cc46bfbd6
4
- data.tar.gz: b6647511a33dfcdf8812be9dc615c7134df5b8ce989b766c6fd6f33886b188d3
3
+ metadata.gz: 1fd62597c79441981462fc6c5a3b6443cec817807eaef28805fdc341e23aa8f5
4
+ data.tar.gz: 5e8fd59f9b5e502be666667e21899054c70aac36c917af0dd1c7f2a6011f3235
5
5
  SHA512:
6
- metadata.gz: 7e797fdfa95678ab2f6811f44f860a0b5018c72fce7654bb11260d35b176dd19ef84c7d1c250f414dd26d643f21596624cf97cff498fd2c27f005845b5dec330
7
- data.tar.gz: de7997dd22b4c59149e1d8b9c565628e959b0636130699997dbb3e339a7debdadc12ac6f5d592eeb188e493b8a7b10d178f7118c6dc798fd839c742a8919b5b8
6
+ metadata.gz: c1c342061a5e4b49636ebc4cceccbaf41e136b10724ca381ebe6051e89cf3924d8f9f0a07b54c8632c3fe8d7b9b3057472d8ee6ff779b7cbeb9b813b4b2eb8d2
7
+ data.tar.gz: e7a67216e1a51588cb58acff908e5180ef1d8ef77d615a8e4b532563e02141e2f9b066b9afe908ec7f2e7b7e11473d857357aac500114cf563799657fc688773
data/data/client/xolo CHANGED
@@ -97,6 +97,7 @@ be_verbose=
97
97
  debugging_on=
98
98
  no_versions=
99
99
  show_xolo_version=
100
+ do_recon=
100
101
 
101
102
  # arguments
102
103
  command=
@@ -155,7 +156,9 @@ Options:
155
156
  policies, etc, from test xolo server, not the production server.
156
157
  Setting the XOLO_TEST_MODE env. variable does the same thing.
157
158
  -r, --recon: With 'install' or 'uninstall' run a 'jamf recon' after the
158
- operation completes successfully.
159
+ operation completes successfully. With 'update', run a 'jamf recon'
160
+ before the checkin. NOTE: With update, the whole process may take
161
+ many minutes.
159
162
  -n, --no-versions: With the 'list-titles' and 'list-installed' commands,
160
163
  do not show the versions available, or the version
161
164
  installed, respectively.
@@ -190,6 +193,9 @@ Commands:
190
193
     every time this computer checks in with Jamf Pro.
191
194
  Note: this just runs the 'jamf policy' command, which will execute any pending
192
195
  Jamf policies triggered by "recurring check-in".
196
+ If --recon is given, a Jamf recon will run first, followed by a 1 minute pause
197
+ for Jamf to process the data before doing the check-in. This helps the Mac to see
198
+ very recently-released versions as patch updates.
193
199
 
194
200
  refresh, r
195
201
  Update xolo's information about current titles and versions.
@@ -1035,6 +1041,12 @@ function run_recon() {
1035
1041
  function update() {
1036
1042
  say "Updating installed titles, or installing newly scoped ones..."
1037
1043
 
1044
+ if [[ -n "$do_recon" ]] ; then
1045
+ run_recon
1046
+ say "Pausing to let Jamf Pro process recon data..."
1047
+ sleep 60
1048
+ fi
1049
+
1038
1050
  debug "Running jamf policy..."
1039
1051
  if be_verbose ; then
1040
1052
  $JAMF policy -verbose
@@ -158,6 +158,8 @@ module Xolo
158
158
  FREEZE_TITLE_CMD = 'freeze'
159
159
  THAW_TITLE_CMD = 'thaw'
160
160
  LIST_FROZEN_CMD = 'list-frozen'
161
+ RERUN_AUTOPKG_RECIPE_CMD = 'rerun-autopkg'
162
+ RERUN_SUBSCRIPTION_CMD = 'rerun-sub'
161
163
 
162
164
  LIST_VERSIONS_CMD = 'list-versions'
163
165
  ADD_VERSION_CMD = 'add-version'
@@ -382,6 +384,10 @@ module Xolo
382
384
  }
383
385
  }.freeze
384
386
 
387
+ DEPLOY_RELEASED = 'released'
388
+ DEPLOY_LATEST = 'latest'
389
+ DEPLOY_SPECIAL_VERSIONS = [DEPLOY_RELEASED, DEPLOY_LATEST].freeze
390
+
385
391
  DEPLOY_VERSION_OPTIONS = {
386
392
  groups: {
387
393
  label: 'Computer group whose computers will be targeted',
@@ -518,17 +524,6 @@ module Xolo
518
524
  confirmation: true
519
525
  },
520
526
 
521
- # SUBSCRIBE_CMD => {
522
- # desc: 'Subscribe to a software title from a Patch Source defined in Jamf Pro',
523
- # display: "#{SUBSCRIBE_CMD} title",
524
- # opts: Xolo::Admin::Title.subscribe_cli_opts,
525
- # walkthru_header: "Subscribing to Xolo Title '#{TARGET_TITLE_PLACEHOLDER}'",
526
- # target: :title,
527
- # process_method: :subscribe_title,
528
- # streamed_response: true,
529
- # confirmation: true
530
- # },
531
-
532
527
  EDIT_TITLE_CMD => {
533
528
  desc: 'Edit an exising software title',
534
529
  display: "#{EDIT_TITLE_CMD} title",
@@ -605,6 +600,32 @@ module Xolo
605
600
  process_method: :list_versions
606
601
  },
607
602
 
603
+ RERUN_AUTOPKG_RECIPE_CMD => {
604
+ desc: 'Run the AutoPkg recipe for this title again, and re-upload the new pkg.',
605
+ display: "#{RERUN_AUTOPKG_RECIPE_CMD} title",
606
+ long_desc: <<~ENDLONG,
607
+ The recipe will be run immediately, and the resulting .pkg will be re-uploaded for the latest version of the title.
608
+ ENDLONG
609
+ opts: {},
610
+ target: :title,
611
+ process_method: :rerun_autopkg_recipe,
612
+ streamed_response: true,
613
+ confirmation: true
614
+ },
615
+
616
+ RERUN_SUBSCRIPTION_CMD => {
617
+ desc: 'Re-add the latest version for this title as if a subscription update just happened.',
618
+ display: "#{RERUN_SUBSCRIPTION_CMD} title",
619
+ long_desc: <<~ENDLONG,
620
+ The most recent version of the title, if 'pilot' or 'pending', is deleted and the subscription update process is triggered again to re-create it. Useful when the process had some error the previous time it ran.
621
+ ENDLONG
622
+ opts: {},
623
+ target: :title,
624
+ process_method: :rerun_subscription_update,
625
+ streamed_response: true,
626
+ confirmation: true
627
+ },
628
+
608
629
  ADD_VERSION_CMD => {
609
630
  desc: 'Add a new version to a title, making it available for piloting',
610
631
  display: "#{ADD_VERSION_CMD} title version",
@@ -667,6 +688,8 @@ module Xolo
667
688
  Computers in any excluded-groups for the target will be removed from the list of targets
668
689
  before the MDM command is sent.
669
690
 
691
+ You can use the words '#{DEPLOY_RELEASED}' or '#{DEPLOY_LATEST}' as the version, or a specific one.
692
+
670
693
  Computers can be specified by name, serial number, or Jamf ID. Groups can be specified by
671
694
  name.
672
695
 
@@ -513,6 +513,42 @@ module Xolo
513
513
  handle_processing_error e
514
514
  end
515
515
 
516
+ # Re run the autopkg recipe
517
+ ################################
518
+ def rerun_autopkg_recipe
519
+ return unless confirmed? "Re-run the AutoPkg recipe for '#{cli_cmd.title}' and re-upload the new pkg"
520
+
521
+ title = Xolo::Admin::Title.fetch cli_cmd.title, server_cnx
522
+ response_data = title.rerun_autopkg_recipe server_cnx
523
+
524
+ show_debug "response_data: #{response_data}"
525
+
526
+ display_progress response_data[:progress_stream_url_path]
527
+
528
+ speak "Recipe has run for '#{cli_cmd.title}'. Please wait up to 15 minutes for a new pkg to be available."
529
+ rescue StandardError => e
530
+ handle_processing_error e
531
+ end
532
+
533
+ #
534
+ ###########################
535
+ def rerun_subscription_update
536
+ unless confirmed? "Delete and re-create the latest version of '#{cli_cmd.title}' via the subscription process?"
537
+ return
538
+ end
539
+
540
+ title = Xolo::Admin::Title.fetch cli_cmd.title, server_cnx
541
+ response_data = title.rerun_subscription_update server_cnx
542
+
543
+ show_debug "response_data: #{response_data}"
544
+
545
+ display_progress response_data[:progress_stream_url_path]
546
+
547
+ speak "Subscription update for latest version of '#{cli_cmd.title}' has been triggered."
548
+ rescue StandardError => e
549
+ handle_processing_error e
550
+ end
551
+
516
552
  # List all versions of a title in Xolo
517
553
  #
518
554
  # @return [void]
@@ -648,7 +684,23 @@ module Xolo
648
684
  # @return [void]
649
685
  ###############################
650
686
  def deploy_version
651
- return unless confirmed? "Deploy Version '#{cli_cmd.version}' of Title '#{cli_cmd.title}' via MDM?"
687
+ # If version is 'latest' or 'released', figure out the actual version to deploy
688
+ if Xolo::Admin::Options::DEPLOY_SPECIAL_VERSIONS.include? cli_cmd.version
689
+ title = Xolo::Admin::Title.fetch cli_cmd.title, server_cnx
690
+ vers_display =
691
+ case cli_cmd.version
692
+ when Xolo::Admin::Options::DEPLOY_RELEASED
693
+ cli_cmd.version = title.released_version
694
+ "#{cli_cmd.version} (#{Xolo::Admin::Options::DEPLOY_RELEASED})"
695
+ when Xolo::Admin::Options::DEPLOY_LATEST
696
+ cli_cmd.version = title.version_order.first
697
+ "#{cli_cmd.version} (#{Xolo::Admin::Options::DEPLOY_LATEST})"
698
+ else
699
+ cli_cmd.version
700
+ end
701
+ end
702
+
703
+ return unless confirmed? "Deploy Version '#{vers_display}' of Title '#{cli_cmd.title}' via MDM?"
652
704
 
653
705
  unless json? || quiet?
654
706
  puts "Deploying Version '#{cli_cmd.version}' of Title '#{cli_cmd.title}' to computers: #{ARGV.join(', ')}"
@@ -966,7 +1018,7 @@ module Xolo
966
1018
  next
967
1019
  end
968
1020
 
969
- vers = Gem::Version.new(d[:version])
1021
+ vers = d[:version]
970
1022
  version_counts[vers] ||= 0
971
1023
  version_counts[vers] += 1
972
1024
  end
@@ -216,6 +216,22 @@ module Xolo
216
216
  resp.body
217
217
  end
218
218
 
219
+ # Rerun the autopkg recipe for this title
220
+ # @param cnx [Faraday::Connection] The connection to use, must be logged in already
221
+ # @return [Hash] the response data
222
+ #########################
223
+ def rerun_autopkg_recipe(cnx = self.cnx)
224
+ resp = cnx.post "#{SERVER_ROUTE}/#{title}/rerun_autopkg_recipe", {}
225
+ resp.body
226
+ end
227
+
228
+ #
229
+ #########################
230
+ def rerun_subscription_update(cnx = self.cnx)
231
+ resp = cnx.post "#{SERVER_ROUTE}/#{title}/rerun-subscription", {}
232
+ resp.body
233
+ end
234
+
219
235
  # Fetch the frozen computers for this title
220
236
  # @param cnx [Faraday::Connection] The connection to use, must be logged in already
221
237
  # @return [Hash{String => String}] computer name => user name
@@ -369,19 +369,18 @@ module Xolo
369
369
  # validate a title auto_release_delay:
370
370
  # - a non-negative integer?
371
371
  # OR
372
+ # - 'monthly'
373
+ # OR
372
374
  # - 'none' to unset the value
373
375
  #
374
376
  # @param val [Object] The value to validate
375
377
  #
376
- # @return [String, Integer] The valid value
378
+ # @return [String] The valid value
377
379
  ###########################
378
- def validate_auto_release_delay
380
+ def validate_auto_release_delay(val)
379
381
  return if val == Xolo::NONE
380
-
381
- if val.pix_integer?
382
- val = val.to_i
383
- return val unless val.negative?
384
- end
382
+ return Xolo::MONTHLY if val.casecmp? Xolo::MONTHLY
383
+ return val if val.pix_integer? && !val.to_i.negative?
385
384
 
386
385
  raise_invalid_data_error val, TITLE_ATTRS[:auto_release_delay][:invalid_msg]
387
386
  end
@@ -953,6 +952,9 @@ module Xolo
953
952
  # if targeting 'all' can't be in self-service
954
953
  validate_title_consistency_no_all_in_ssvc(opts)
955
954
 
955
+ # if target_groups is set, release_group scan't be all, and vice versa
956
+ validate_title_consistency_no_tgt_groups_with_all(opts)
957
+
956
958
  # if self-service category given, must be in self-service
957
959
  validate_title_consistency_ssvc_needs_category(opts)
958
960
 
@@ -1197,7 +1199,7 @@ module Xolo
1197
1199
  end
1198
1200
  end
1199
1201
 
1200
- # if target_group is all, can't be in self service
1202
+ # if release_groups is all, can't be in self service
1201
1203
  #
1202
1204
  # @param opts [OpenStruct] the current options
1203
1205
  #
@@ -1208,13 +1210,33 @@ module Xolo
1208
1210
 
1209
1211
  msg =
1210
1212
  if walkthru?
1211
- "Cannot be in Self Service when Target Group is '#{Xolo::TARGET_ALL}'"
1213
+ "Cannot be in Self Service when Release Group is '#{Xolo::TARGET_ALL}'"
1212
1214
  else
1213
1215
  "--self-service cannot be used when --release-groups contains '#{Xolo::TARGET_ALL}'"
1214
1216
  end
1215
1217
  raise_consistency_error msg
1216
1218
  end
1217
1219
 
1220
+ # if target_groups is set, release_group scan't be all, and vice versa
1221
+ #
1222
+ # @param opts [OpenStruct] the current options
1223
+ #
1224
+ # @return [void]
1225
+ #######
1226
+ def validate_title_consistency_no_tgt_groups_with_all(opts)
1227
+ rel_all = opts[:release_groups].to_a.include?(Xolo::TARGET_ALL)
1228
+ got_tgts = !opts[:target_groups].pix_empty?
1229
+ return unless rel_all && got_tgts
1230
+
1231
+ msg =
1232
+ if walkthru?
1233
+ "Cannot use Target Group when Release Group is '#{Xolo::TARGET_ALL}'"
1234
+ else
1235
+ "--target-groups cannot be used when --release-groups contains '#{Xolo::TARGET_ALL}'"
1236
+ end
1237
+ raise_consistency_error msg
1238
+ end
1239
+
1218
1240
  # if in self service, a category must be assigned
1219
1241
  #
1220
1242
  # @param opts [OpenStruct] the current options
data/lib/xolo/admin.rb CHANGED
@@ -20,25 +20,33 @@
20
20
  ######
21
21
  require 'openssl'
22
22
 
23
- # Monkeypatch OpenSSL::SSL::SSLContext to ignore unexpected EOF errors
24
- # happens with openssl v3 ??
23
+ # Monkeypatch/workaround so that OpenSSL::SSL::SSLContext ignores unexpected EOF errors...
24
+ # Seems to be a known problem with openssl v3.x
25
+ #
25
26
  # see https://stackoverflow.com/questions/76183622/since-a-ruby-container-upgrade-we-expirience-a-lot-of-opensslsslsslerror
27
+ # and other googlings.
28
+ #
29
+ # In ruby 4.0 OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] is frozen so we have to .dup it
30
+ # to make the change.
31
+ #
32
+ # TODO: Remove this when the underlying problem is fixed, in either openssl itself, or
33
+ # the OpenSSL ruby module.
26
34
  if OpenSSL::SSL.const_defined?(:OP_IGNORE_UNEXPECTED_EOF)
35
+ if OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.frozen?
36
+ # supress redefined const. warning
37
+ original_verbose = $VERBOSE
38
+ $VERBOSE = nil
39
+ OpenSSL::SSL::SSLContext::DEFAULT_PARAMS = OpenSSL::SSL::SSLContext::DEFAULT_PARAMS.dup
40
+ $VERBOSE = original_verbose
41
+ end
42
+
27
43
  OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] |= OpenSSL::SSL::OP_IGNORE_UNEXPECTED_EOF
28
44
  end
29
45
 
30
- require 'openssl'
31
46
  require 'faraday'
32
47
  require 'faraday/multipart'
33
48
  require 'highline'
34
49
 
35
- # Monkeypatch OpenSSL::SSL::SSLContext to ignore unexpected EOF errors
36
- # happens with openssl v3 ??
37
- # see https://stackoverflow.com/questions/76183622/since-a-ruby-container-upgrade-we-expirience-a-lot-of-opensslsslsslerror
38
- if OpenSSL::SSL.const_defined?(:OP_IGNORE_UNEXPECTED_EOF)
39
- OpenSSL::SSL::SSLContext::DEFAULT_PARAMS[:options] |= OpenSSL::SSL::OP_IGNORE_UNEXPECTED_EOF
40
- end
41
-
42
50
  # Yes we're using a OpenStruct for our @opts, even though it's very slow.
43
51
  # It isn't so slow that it's a problem for processing a CLI tool.
44
52
  # The benefit is being able to use either Hash-style references
@@ -459,15 +459,17 @@ module Xolo
459
459
  },
460
460
 
461
461
  # @!attribute auto_release_delay
462
- # @return [String] 'none' or an integer in string. How many days before new versions are automatically released?
462
+ # @return [String] 'none', 'monthly', or an integer in string.
463
+ # How many days before new versions are automatically released?
463
464
  # Applies only to subscribed titles with autopkg recipes.
464
465
  auto_release_delay: {
465
466
  label: 'Automatic Release Delay',
466
467
  cli: :A,
467
468
  type: :string,
468
469
  walkthru_na: :auto_release_delay_na,
470
+ validate: true,
469
471
  changelog: true,
470
- invalid_msg: "Must be a non-negative integer, or '#{Xolo::NONE}'.",
472
+ invalid_msg: "Must be a non-negative integer, '#{Xolo::MONTHLY}', or '#{Xolo::NONE}'.",
471
473
  desc: <<~ENDDESC
472
474
  Specify how many days after a new version appears before it is automatically released from pilot.
473
475
 
@@ -477,6 +479,8 @@ module Xolo
477
479
 
478
480
  Setting it to zero means that new versions will be released at the next nightly auto-release task. *** USE WITH EXTREME CAUTION ***
479
481
 
482
+ Setting it to '#{Xolo::MONTHLY}' will release it on whatever day of the month is defined in the Xolo server's 'auto_release_monthly' setting, or on the first day of the month if the server isn't set. The server may be set to a specific date, like '15' or to an ordinal-weekday, like '3rd Mon'.
483
+
480
484
  To unset, meaning versions are never auto-released, use '#{Xolo::NONE}'
481
485
 
482
486
  Auto-release happens during the server's nightly maintenance between 2-3am.
@@ -23,6 +23,9 @@ module Xolo
23
23
 
24
24
  ERROR = 'ERROR'
25
25
 
26
+ # A possible value for a title's auto-release delay
27
+ MONTHLY = 'monthly'
28
+
26
29
  # Several things use x
27
30
  X = 'x'
28
31
 
@@ -12,7 +12,7 @@ module Xolo
12
12
 
13
13
  module Version
14
14
 
15
- VERSION = '2.3.0'.freeze
15
+ VERSION = '2.5.0'.freeze
16
16
 
17
17
  end
18
18
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: xolo-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.0
4
+ version: 2.5.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-09-04 00:00:00.000000000 Z
11
+ date: 2026-10-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday