xolo-server 2.3.0 → 2.4.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: e78577a11f1d65aba560ec5540c3a79acdfc7d6a491060e256bb9e2da5a057d9
4
- data.tar.gz: 9e7e776f48e8e9e260bc41a9090603bbfc41d1dad7dd62fc00396ce9914450cb
3
+ metadata.gz: d27f4a3e1656ef59731865488978113bcbeb4a5ebbea8c120585371c49aad335
4
+ data.tar.gz: a006f5ec49ad3cfbad6ae5908e2da17b65cdc2bf8eb0c3a7133fcaa0af6db3f4
5
5
  SHA512:
6
- metadata.gz: b83f99bda3666a2fd124241a26882499c393a75b3289fb503bdcb6ac994827228b5f813acc79a7a81f437f879b2e9aaca727800ddd711f17b2713d7a45a98738
7
- data.tar.gz: 05bb86ec68010bf2258853983f093936ffa735c52144b6760c64177621a971bdf93823a46562a4b347c5a080d5206900a39ff8b6019e7fb1fa0cf0b400e4336e
6
+ metadata.gz: c47f0964d7c5f5a42ddb909a0ee6b5d8bb01ead710b6be7fe9087e882081dcf753fc9f783be8bd0e5658b49df36d012f59f956db768026c915faabc8f5d9a4a8
7
+ data.tar.gz: 448ec9e58919ada9612c8651f814d168d4d6117c92b3e76faa2c5bdc74eb7747298f6bdebcc1547b7c662084d97fbbd7fb018331c8424f28b79bf1114cdacba7
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
@@ -12,7 +12,7 @@ module Xolo
12
12
 
13
13
  module Version
14
14
 
15
- VERSION = '2.3.0'.freeze
15
+ VERSION = '2.4.0'.freeze
16
16
 
17
17
  end
18
18
 
@@ -156,6 +156,7 @@ module Xolo
156
156
 
157
157
  # @!attribute server_admin_jamf_group
158
158
  # @return [String] The name of a Jamf account-group containing users of 'xadm'
159
+ # who are allowed to manage the xoloserver itself
159
160
  server_admin_jamf_group: {
160
161
  type: :string,
161
162
  desc: <<~ENDDESC
@@ -35,6 +35,11 @@ module Xolo
35
35
  AUTOPKG_UPLOADED_BY = 'autopkg'
36
36
  FAIL_UNTRUSTED_RECIPES_CLI_OPT = '-k FAIL_RECIPES_WITHOUT_TRUST_INFO=yes'
37
37
 
38
+ # when we find a .pkg after a recipe has run, it can't be older than this many
39
+ # seconds, or we assume it is from some other run of the recipe, not the one we
40
+ # just did. Currently 20 min
41
+ MAX_PKG_AGE = 1200
42
+
38
43
  # Module Methods
39
44
  #######################
40
45
  #######################
@@ -127,7 +132,9 @@ module Xolo
127
132
  clean_old_pkgs pkgdir
128
133
 
129
134
  cmd = autopkg_run_command(title_object)
130
- progress "Running AutoPkg recipe for #{title_object.title} via command: #{cmd.join(' ')}", log: :info
135
+ progress "Running AutoPkg recipe '#{recipe}' for #{title_object.title}..."
136
+
137
+ log_info "Running AutoPkg recipe for #{title_object.title} via command: #{cmd.join(' ')}"
131
138
 
132
139
  unlock_autopkg_user_keychain
133
140
 
@@ -135,20 +142,83 @@ module Xolo
135
142
  souterr.strip!
136
143
 
137
144
  if status.success?
138
- progress "AutoPkg recipe #{recipe} for title '#{title_object.title}' completed successfully.", log: :info, alert: true
145
+ progress "AutoPkg recipe '#{recipe}' for title '#{title_object.title}' completed successfully.", log: :info, alert: true
139
146
  log_debug 'AutoPkg output:'
140
147
  souterr.lines.each { |l| log_debug "AutoPkg: #{l.chomp}" }
141
148
 
142
149
  pkgs = pkgdir.children.select { |c| c.extname == '.pkg' }
150
+ # the Pathname of the newest .pkg
143
151
  pkgs.max_by(&:mtime)
144
152
 
153
+ # Failure is a option
145
154
  else
146
- progress "ERROR: AutoPkg recipe #{recipe} failed with status #{status.exitstatus}.", log: :error, alert: true
147
- log_error 'AutoPkg output:'
148
- souterr.lines.each { |l| log_error "AutoPkg: #{l.chomp}" }
155
+ handle_failed_recipe(
156
+ recipe: recipe,
157
+ title_object: title_object,
158
+ status: status,
159
+ souterr: souterr
160
+ )
161
+ end
162
+ end
163
+
164
+ # Deal with a failed recipe run
165
+ #
166
+ ###############################
167
+ def handle_failed_recipe(recipe:, title_object:, status:, souterr:)
168
+ errmsg = "ERROR: AutoPkg recipe '#{recipe}' for title '#{title_object.title}' failed with status #{status.exitstatus}. Details logged and emailed to '#{title_object.contact_email}'"
169
+
170
+ progress errmsg, log: :error, alert: true
171
+
172
+ # log the details
173
+ log_error 'AutoPkg output:'
174
+ souterr.lines.each { |l| log_error "AutoPkg: #{l.chomp}" }
175
+
176
+ # email the details to the contact addr for the title
177
+ email_subj = "ERROR: AutoPkg recipe FAILED for title '#{title_object.title}'"
178
+ email_msg = <<~ENDEMAIL
179
+ The autopkg recipe '#{recipe}' for title '#{title_object.title}' failed with status #{status.exitstatus}.
180
+
181
+ Please check that the recipe is up to date. If not, please update the recipe's repo by running this as the autppkg user on the xolo server:
182
+
183
+ autopkg repo-update <repo-name>
184
+
185
+ Then confirm you still trust the recipe.
186
+ If so, run:
187
+
188
+ autopkg update-trust-info '#{recipe}'
189
+
190
+ Then tell xolo the xolo server to re-run the recipe - the .pkg will always be assigned to the latest version.
191
+
192
+ xadm rerun-autopkg-recipe #{title_object.title}
193
+
194
+ If needed, contact your xoloserver administrator to perform the autopkg commands.
195
+
196
+ Here is the output from the failed recipe:
197
+ ------------------------------------------
198
+ #{souterr}
199
+ ENDEMAIL
200
+
201
+ send_email to: title_object.contact_email, subject: email_subj, msg: email_msg, html: false
202
+
203
+ raise "AutoPkg recipe #{recipe} failed."
204
+ end
205
+
206
+ # confirm a given autopkg package is OK to use after running a recipe
207
+ ###########################
208
+ def validate_autopkg_pkg(pkg_src)
209
+ if pkg_src.nil?
210
+ msg = 'AutoPkg recipe is enabled for this title, but no pkg was found after running the recipe. Please check the AutoPkg recipe and the server log for details.'
211
+ progress msg, log: :warn, alert: true
212
+ return false
213
+ end
149
214
 
150
- raise "AutoPkg recipe #{recipe} failed."
215
+ oldest_allowed = Time.now - MAX_PKG_AGE # 20 minutes ago
216
+ if pkg_src.mtime < oldest_allowed
217
+ msg = "AutoPkg recipe is enabled for this title, and a pkg was found after running the recipe, but it was last modified at #{pkg_src.mtime}, which is more than 20 minutes ago. To avoid accidentally uploading an old pkg, the server will not upload this pkg. Please check the AutoPkg recipe and the server log for details."
218
+ progress msg, log: :warn, alert: true
219
+ return false
151
220
  end
221
+ true
152
222
  end
153
223
 
154
224
  # remove any existing pkgs from the given autopkg output dir
@@ -334,13 +334,13 @@ module Xolo
334
334
  next unless vobj_to_release
335
335
 
336
336
  # release it
337
- log_debug "Maint: About to auto-release version '#{vobj_to_release.version}' of '#{title}' which came out #{vobj_to_release.creation_date}"
337
+ log_debug "Maint: About to auto-release '#{title}' version '#{vobj_to_release.version}' which came out #{vobj_to_release.creation_date}"
338
338
 
339
339
  # releasing a version is done via the title obj, since it affects the status
340
340
  # of all versions.
341
341
  title_obj.release vobj_to_release.version
342
342
 
343
- log_info "Maint: Auto-released version '#{vobj_to_release.version}' of '#{title}' which came out #{vobj_to_release.creation_date}", alert: true
343
+ log_info "Maint: Auto-released '#{title}' version '#{vobj_to_release.version}' which came out #{vobj_to_release.creation_date}", alert: true
344
344
 
345
345
  # pause for server to catch up
346
346
  sleep 60
@@ -1808,6 +1808,8 @@ module Xolo
1808
1808
  pol.self_service_description = new_desc
1809
1809
 
1810
1810
  pol.self_service_install_button_text = Xolo::Server::Title::SELF_SERVICE_INSTALL_BTN_TEXT
1811
+ pol.self_service_reinstall_button_text = Xolo::Server::Title::SELF_SERVICE_REINSTALL_BTN_TEXT
1812
+
1811
1813
  # icon already uploaded to jamf
1812
1814
  return if ssvc_icon_id
1813
1815
 
@@ -1823,13 +1825,6 @@ module Xolo
1823
1825
  self.ssvc_icon_id = Jamf::Policy.fetch(id: pol.id, cnx: jamf_cnx).icon.id
1824
1826
  end
1825
1827
 
1826
- # run the autopkg recipe if defined
1827
- # See Helpers::AutoPkg for more details
1828
- ############################
1829
- def run_autopkg_recipe
1830
- server_app_instance.run_autopkg_recipe self
1831
- end
1832
-
1833
1828
  # Methods used by subscription stuff
1834
1829
  ##############################
1835
1830
 
@@ -288,6 +288,30 @@ module Xolo
288
288
  body data
289
289
  end
290
290
 
291
+ # rerun the titles autopkg recipe
292
+ ######################
293
+ post '/titles/:title/rerun_autopkg_recipe' do
294
+ halt_on_missing_title params[:title]
295
+ halt_on_locked_title params[:title]
296
+ title = instantiate_title params[:title]
297
+
298
+ unless title.autopkg_enabled?
299
+ msg = "Title '#{params[:title]}' is not configured to use AutoPkg"
300
+ log_debug "ERROR: #{msg}"
301
+ halt 409, { status: 409, error: msg }
302
+ end
303
+
304
+ unless title.latest_version
305
+ msg = "Title '#{params[:title]}' has no versions, cannot re-run the recipe"
306
+ log_debug "ERROR: #{msg}"
307
+ halt 404, { status: 404, error: msg }
308
+ end
309
+
310
+ with_streaming do
311
+ title.rerun_autopkg_recipe
312
+ end
313
+ end
314
+
291
315
  end # Titles
292
316
 
293
317
  end # Routes
@@ -120,6 +120,7 @@ module Xolo
120
120
  JPAPI_PATCH_REPORT_RSRC = 'patch-report'
121
121
 
122
122
  SELF_SERVICE_INSTALL_BTN_TEXT = 'Install'
123
+ SELF_SERVICE_REINSTALL_BTN_TEXT = 'Re-Install'
123
124
 
124
125
  # Class Methods
125
126
  ######################
@@ -1144,6 +1145,27 @@ module Xolo
1144
1145
  unlock
1145
1146
  end
1146
1147
 
1148
+ # run the autopkg recipe if defined
1149
+ # See Helpers::AutoPkg for more details
1150
+ ############################
1151
+ def run_autopkg_recipe
1152
+ server_app_instance.run_autopkg_recipe self
1153
+ end
1154
+
1155
+ # Re run the autopkg recipe
1156
+ # and re-upload the pkg
1157
+ ############################
1158
+ def rerun_autopkg_recipe
1159
+ pkg_src = server_app_instance.run_autopkg_recipe self
1160
+
1161
+ return unless server_app_instance.validate_autopkg_pkg pkg_src
1162
+
1163
+ latest_version_obj = version_object latest_version
1164
+ latest_version_obj.pkg_is_from_autopkg = true
1165
+
1166
+ server_app_instance.process_and_upload_autopkg_pkg title, latest_version_obj, pkg_src
1167
+ end
1168
+
1147
1169
  # Is this title locked for updates?
1148
1170
  #############################
1149
1171
  def locked?
@@ -748,18 +748,7 @@ module Xolo
748
748
 
749
749
  pkg_src = title_object.run_autopkg_recipe
750
750
 
751
- if pkg_src.nil?
752
- msg = 'AutoPkg recipe is enabled for this title, but no pkg was found after running the recipe. Please check the AutoPkg recipe and the server log for details.'
753
- progress msg, log: :warn, alert: true
754
- return
755
- end
756
-
757
- oldest_allowed = Time.now - 1200 # 20 minutes ago
758
- if pkg_src.mtime < oldest_allowed
759
- msg = "AutoPkg recipe is enabled for this title, and a pkg was found after running the recipe, but it was last modified at #{pkg_src.mtime}, which is more than 20 minutes ago. To avoid accidentally uploading an old pkg, the server will not upload this pkg. Please check the AutoPkg recipe and the server log for details."
760
- progress msg, log: :warn, alert: true
761
- return
762
- end
751
+ return unless server_app_instance.validate_autopkg_pkg pkg_src
763
752
 
764
753
  # this lets future code know that the pkg we're working with came from autopkg
765
754
  self.pkg_is_from_autopkg = true
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.3.0
4
+ version: 2.4.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-09-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday