xolo-server 1.0.0 → 1.0.1
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 +4 -4
- data/README.md +42 -4
- data/bin/xoloserver +3 -0
- data/data/client/xolo +1160 -0
- data/lib/optimist_with_insert_blanks.rb +1216 -0
- data/lib/xolo/core/base_classes/configuration.rb +238 -0
- data/lib/xolo/core/base_classes/server_object.rb +112 -0
- data/lib/xolo/core/base_classes/title.rb +648 -0
- data/lib/xolo/core/base_classes/version.rb +601 -0
- data/lib/xolo/core/constants.rb +81 -0
- data/lib/xolo/core/exceptions.rb +52 -0
- data/lib/xolo/core/json_wrappers.rb +43 -0
- data/lib/xolo/core/loading.rb +59 -0
- data/lib/xolo/core/output.rb +292 -0
- data/lib/xolo/core/version.rb +21 -0
- data/lib/xolo/core.rb +46 -0
- data/lib/xolo/server/configuration.rb +1 -2
- data/lib/xolo/server/helpers/jamf_pro.rb +1 -0
- data/lib/xolo/server/mixins/title_jamf_access.rb +7 -12
- data/lib/xolo/server/mixins/title_ted_access.rb +21 -5
- data/lib/xolo/server/mixins/version_jamf_access.rb +23 -17
- data/lib/xolo/server/mixins/version_ted_access.rb +9 -4
- data/lib/xolo/server/routes.rb +6 -23
- data/lib/xolo/server/version.rb +1 -3
- metadata +21 -10
|
@@ -0,0 +1,648 @@
|
|
|
1
|
+
# Copyright 2025 Pixar
|
|
2
|
+
#
|
|
3
|
+
# Licensed under the terms set forth in the LICENSE.txt file available at
|
|
4
|
+
# at the root of this project.
|
|
5
|
+
#
|
|
6
|
+
#
|
|
7
|
+
|
|
8
|
+
# frozen_string_literal: true
|
|
9
|
+
|
|
10
|
+
# main module
|
|
11
|
+
module Xolo
|
|
12
|
+
|
|
13
|
+
module Core
|
|
14
|
+
|
|
15
|
+
module BaseClasses
|
|
16
|
+
|
|
17
|
+
# The base class for dealing with Titles in the
|
|
18
|
+
# Xolo Server, Admin, and Client modules.
|
|
19
|
+
#
|
|
20
|
+
# This class holds the common aspects of Xolo Titles as used
|
|
21
|
+
# on the Xolo server, in the Xolo Admin CLI app 'xadm', and the
|
|
22
|
+
# client app 'xolo' - most importately it defines which data they
|
|
23
|
+
# exchange.
|
|
24
|
+
#
|
|
25
|
+
############################
|
|
26
|
+
class Title < Xolo::Core::BaseClasses::ServerObject
|
|
27
|
+
|
|
28
|
+
# Mixins
|
|
29
|
+
#############################
|
|
30
|
+
#############################
|
|
31
|
+
|
|
32
|
+
# Constants
|
|
33
|
+
#############################
|
|
34
|
+
#############################
|
|
35
|
+
|
|
36
|
+
MIN_TITLE_DESC_LENGTH = 25
|
|
37
|
+
|
|
38
|
+
# Attributes
|
|
39
|
+
######################
|
|
40
|
+
######################
|
|
41
|
+
|
|
42
|
+
# Attributes of Titles.
|
|
43
|
+
#
|
|
44
|
+
# This hash defines the common attributes of all Xolo titles - which should
|
|
45
|
+
# be available in all subclasses, both on the server, in xadm, and via the
|
|
46
|
+
# client.
|
|
47
|
+
#
|
|
48
|
+
# Each of those subclasses might define (and store or calculate) other
|
|
49
|
+
# attributes as needed.
|
|
50
|
+
#
|
|
51
|
+
# Importantly, the attributes defined here are those that are transfered
|
|
52
|
+
# between xadm and the server as JSON data, and then used to instantiate the
|
|
53
|
+
# title in the local context. They are also stored in the JSON file deployed
|
|
54
|
+
# to clients containing all currently known titles and versions.
|
|
55
|
+
#
|
|
56
|
+
# In this hash, each key is the name of an attribute, and the values are
|
|
57
|
+
# hashes defining the details of that attribute.
|
|
58
|
+
#
|
|
59
|
+
# Since they are used by all subclasses, the details may include info used
|
|
60
|
+
# by one subclass but not another. For example, these attributes are
|
|
61
|
+
# used to create/define CLI & walkthru options for xadm, the settings for
|
|
62
|
+
# which are ignored on the server.
|
|
63
|
+
#
|
|
64
|
+
# The info below also applies to {Xolo:Core::BaseClasses::Version::ATTRIBUTES}, q.v.
|
|
65
|
+
#
|
|
66
|
+
# Title attributes have these details:
|
|
67
|
+
#
|
|
68
|
+
# - label: [String] to be displayed in admin interaction, walkthru, help msgs
|
|
69
|
+
# or error messages. e.g. 'Display Name' for the attribute display_name
|
|
70
|
+
#
|
|
71
|
+
# - required: [Boolean] Must be provided when making a new title, cannot be
|
|
72
|
+
# deleted from existing titles. (but can be changed if not immutable)
|
|
73
|
+
#
|
|
74
|
+
# - immutable: [Boolean] This value can only be set when creatimg a new title.
|
|
75
|
+
# When editing an existing title, it cannot be changed.
|
|
76
|
+
#
|
|
77
|
+
# - cli: [Symbol, false] What is the 'short' option flag for this option?
|
|
78
|
+
# The long option flag is the key, preceded with '--' and with underscores
|
|
79
|
+
# changed to '-', so display_name is set using the cli option '--display-name'.
|
|
80
|
+
# If this is set to :n then the short version is '-n'
|
|
81
|
+
#
|
|
82
|
+
# If this attribute can't be set via walkthru or a CLI option, set this to false.
|
|
83
|
+
#
|
|
84
|
+
# - multi: [Boolean] If true, this option takes multiple values and is stored as
|
|
85
|
+
# an Array. On the commandline, it can be given multiple times and all the values
|
|
86
|
+
# will be in an array in the options hash.
|
|
87
|
+
# E.g. if foo: { multi: true } and these options are given on the commandline
|
|
88
|
+
# --foo val1 --foo val2 --foo 'val 3'
|
|
89
|
+
# then the options hash will contain: :foo => ['val1', 'val2', 'val 3']
|
|
90
|
+
# It can also be given as a single comma-separated string, e.g.
|
|
91
|
+
# --foo 'val1, val2, val 3'
|
|
92
|
+
#
|
|
93
|
+
# In --walkthru the user will be asked to keep entering values, and to
|
|
94
|
+
# end input with an 'x' by itself.
|
|
95
|
+
#
|
|
96
|
+
# - default: [String, Numeric, Boolean, Proc] the default value if nothing is
|
|
97
|
+
# provided or inherited. Note that titles never inherit values, only versions do.
|
|
98
|
+
#
|
|
99
|
+
# - validate: [Boolean, Symbol] how to validate & convert values for this attribute.
|
|
100
|
+
#
|
|
101
|
+
# - If true (not just truthy) call method named 'validate_<key>' in {Xolo::Admin::Validate}
|
|
102
|
+
# passing in the value to validate.
|
|
103
|
+
# e.g. Xolo::Admin::Validate.validate_display_name(new_display_name)
|
|
104
|
+
#
|
|
105
|
+
# - If a Symbol, it's an arbitrary method to call on the {Xolo::Admin::Validate} module
|
|
106
|
+
# e.g. :non_empty_array will validate the value using
|
|
107
|
+
# Xolo::Admin::Validate.non_empty_array(some_array_value)
|
|
108
|
+
#
|
|
109
|
+
# - Anything else: no validation, and the value will be a String
|
|
110
|
+
#
|
|
111
|
+
# - type: [Symbol] the data type of the value. One of: :boolean, :string, :integer,
|
|
112
|
+
# :time
|
|
113
|
+
#
|
|
114
|
+
# NOTE: We are not using Optimist's validation & auto-conversion of these types, they
|
|
115
|
+
# all come from the CLI as strings, and the matching method in {Xolo::Admin::Validate}
|
|
116
|
+
# is used to validate and convert the values.
|
|
117
|
+
# The YARD docs for each attribute indicate the Class of the value in the
|
|
118
|
+
# Title object after CLI processing.
|
|
119
|
+
#
|
|
120
|
+
# - invalid_msg: [String] Custom message to display when the value fails validation.
|
|
121
|
+
#
|
|
122
|
+
# - desc: [String] Helpful text explaining what the attribute is, and what its CLI option means.
|
|
123
|
+
# Displayed during walkthru, in help messages, and in some err messages.
|
|
124
|
+
#
|
|
125
|
+
# - walkthru_na: [Symbol] The name of a method to call (usually defined in
|
|
126
|
+
# {Xolo::Admin::Interactive}) when building the walk thru menu item for this option.
|
|
127
|
+
# If it returns a string, it is an explanation of wny this option
|
|
128
|
+
# is not available at the moment, and the item is not selectable. If it returns nil, the
|
|
129
|
+
# item is displayed and handled as normal.
|
|
130
|
+
#
|
|
131
|
+
# - multiline [Boolean] If true, the value for this option can be many lines lione, and in
|
|
132
|
+
# walkthru, will be presented to the user in an editor like vim. See also multi: above
|
|
133
|
+
#
|
|
134
|
+
# - ted_attribute: [Symbol] If this attribute has a matching one on the related
|
|
135
|
+
# Title Editor Title, this is the name of that attribute in the Windoo::SoftwareTitle
|
|
136
|
+
#
|
|
137
|
+
# - readline: [Symbol] If set, use readline to get the value from the user during walkthru.
|
|
138
|
+
# If the symbol is :get_files, a custom method is called that uses readline with shell-style
|
|
139
|
+
# auto-complete to get one or more file paths.
|
|
140
|
+
# Any other symbol is the name of a method to call, which will return an array of possible
|
|
141
|
+
# values for the option, which will be used for readline-based auto-completion.
|
|
142
|
+
#
|
|
143
|
+
# - readline_prompt: When using readline to gather mulit: values, this prompt is shown at the
|
|
144
|
+
# start of each line of input for the next item.
|
|
145
|
+
#
|
|
146
|
+
# - read_only: [Boolean] defaults to false. When true, the server maintains this value, and
|
|
147
|
+
# its only readable via xadm.
|
|
148
|
+
#
|
|
149
|
+
# - hide_from_info: [Boolean] when true, do not show this attribute in the 'info' xadm output
|
|
150
|
+
# NOTE: it will still be available when --json is given with the info command.
|
|
151
|
+
#
|
|
152
|
+
# - changelog: [Boolean] When true, changes to this attribute is included in the changelog for the title.
|
|
153
|
+
#
|
|
154
|
+
ATTRIBUTES = {
|
|
155
|
+
|
|
156
|
+
# @!attribute title
|
|
157
|
+
# @return [String] The unique title-string for this title.
|
|
158
|
+
title: {
|
|
159
|
+
label: 'Title',
|
|
160
|
+
ted_attribute: :id,
|
|
161
|
+
required: true,
|
|
162
|
+
immutable: true,
|
|
163
|
+
cli: false,
|
|
164
|
+
type: :string,
|
|
165
|
+
hide_from_info: true,
|
|
166
|
+
validate: true,
|
|
167
|
+
invalid_msg: 'Not a valid title: must be lowercase alphanumeric and dashes only',
|
|
168
|
+
desc: <<~ENDDESC
|
|
169
|
+
A unique string identifying this Title, e.g. 'folio' or 'google-chrome'.
|
|
170
|
+
The same as a 'basename' in d3.
|
|
171
|
+
Must contain only lowercase letters, numbers, and dashes.
|
|
172
|
+
ENDDESC
|
|
173
|
+
},
|
|
174
|
+
|
|
175
|
+
# @!attribute display_name
|
|
176
|
+
# @return [String] The display-name for this title
|
|
177
|
+
display_name: {
|
|
178
|
+
label: 'Display Name',
|
|
179
|
+
ted_attribute: :name,
|
|
180
|
+
required: true,
|
|
181
|
+
cli: :n,
|
|
182
|
+
type: :string,
|
|
183
|
+
validate: :validate_title_display_name,
|
|
184
|
+
invalid_msg: 'Not a valid display name, must be at least three characters long.',
|
|
185
|
+
changelog: true,
|
|
186
|
+
desc: <<~ENDDESC
|
|
187
|
+
A human-friendly name for the Software Title, e.g. 'Google Chrome', or 'NFS Menubar'.
|
|
188
|
+
Must be at least three characters long.
|
|
189
|
+
ENDDESC
|
|
190
|
+
},
|
|
191
|
+
|
|
192
|
+
# @!attribute description
|
|
193
|
+
# @return [String] A description of what this title installs
|
|
194
|
+
description: {
|
|
195
|
+
label: 'Description',
|
|
196
|
+
required: true,
|
|
197
|
+
cli: :d,
|
|
198
|
+
type: :string,
|
|
199
|
+
validate: :validate_title_desc,
|
|
200
|
+
changelog: true,
|
|
201
|
+
multiline: true,
|
|
202
|
+
invalid_msg: <<~ENDINV,
|
|
203
|
+
Not a valid description, must be at least #{MIN_TITLE_DESC_LENGTH} characters.
|
|
204
|
+
|
|
205
|
+
Provide a useful dscription of what the software does, URLs, developer names, etc.
|
|
206
|
+
|
|
207
|
+
DO NOT USE, e.g. 'Installs Some App', because we know that already and it isn't helpful.
|
|
208
|
+
ENDINV
|
|
209
|
+
desc: <<~ENDDESC
|
|
210
|
+
A useful dscription of what the software installed by this title does. You can also include URLs, developer names, support info, etc.
|
|
211
|
+
|
|
212
|
+
DO NOT use, e.g. 'Installs Some App', because we know that already and it isn't helpful.
|
|
213
|
+
|
|
214
|
+
IMPORTANT: If this title appears in Self Service, the description will be visible to users.
|
|
215
|
+
|
|
216
|
+
Must be at least #{MIN_TITLE_DESC_LENGTH} Characters.
|
|
217
|
+
ENDDESC
|
|
218
|
+
},
|
|
219
|
+
|
|
220
|
+
# @!attribute publisher
|
|
221
|
+
# @return [String] The entity that publishes this title
|
|
222
|
+
publisher: {
|
|
223
|
+
label: 'Publisher',
|
|
224
|
+
ted_attribute: :publisher,
|
|
225
|
+
required: true,
|
|
226
|
+
cli: :P,
|
|
227
|
+
type: :string,
|
|
228
|
+
validate: true,
|
|
229
|
+
changelog: true,
|
|
230
|
+
invalid_msg: '"Not a valid Publisher, must be at least three characters.',
|
|
231
|
+
desc: <<~ENDDESC
|
|
232
|
+
The company or entity that publishes this title, e.g. 'Apple, Inc.' or 'Pixar Animation Studios'.
|
|
233
|
+
ENDDESC
|
|
234
|
+
},
|
|
235
|
+
|
|
236
|
+
# @!attribute app_name
|
|
237
|
+
# @return [String] The name of the .app installed by this title. Nil if no .app is installed
|
|
238
|
+
app_name: {
|
|
239
|
+
label: 'App Name',
|
|
240
|
+
ted_attribute: :appName,
|
|
241
|
+
cli: :a,
|
|
242
|
+
validate: true,
|
|
243
|
+
type: :string,
|
|
244
|
+
changelog: true,
|
|
245
|
+
walkthru_na: :app_name_bundleid_na,
|
|
246
|
+
invalid_msg: "Not a valid App name, must end with '.app'",
|
|
247
|
+
desc: <<~ENDDESC
|
|
248
|
+
If this title installs a .app bundle, the app's name must be provided. This the name of the bundle itself on disk, e.g. 'Google Chrome.app'.
|
|
249
|
+
|
|
250
|
+
Jamf Patch Management uses this, plus the app's bundle id, to determine if the title is installed on a computer, and if so, which version.
|
|
251
|
+
|
|
252
|
+
If the title does not install a .app bundle, leave this blank, and provide a --version-script.
|
|
253
|
+
|
|
254
|
+
REQUIRED if --app-bundle-id is used.
|
|
255
|
+
ENDDESC
|
|
256
|
+
},
|
|
257
|
+
|
|
258
|
+
# @!attribute app_bundle_id
|
|
259
|
+
# @return [String] The bundle ID of the .app installed by this title. Nil if no .app is installed
|
|
260
|
+
app_bundle_id: {
|
|
261
|
+
label: 'App Bundle ID',
|
|
262
|
+
ted_attribute: :bundleId,
|
|
263
|
+
cli: :b,
|
|
264
|
+
validate: true,
|
|
265
|
+
type: :string,
|
|
266
|
+
changelog: true,
|
|
267
|
+
walkthru_na: :app_name_bundleid_na,
|
|
268
|
+
invalid_msg: '"Not a valid bundle-id, must include at least one dot.',
|
|
269
|
+
desc: <<~ENDDESC
|
|
270
|
+
If this title installs a .app bundle, the app's bundle-id must be provided. This is found in the CFBundleIdentifier key of the app's Info.plist, e.g. 'com.google.chrome'
|
|
271
|
+
|
|
272
|
+
Jamf Patch Management uses this, plus the app's name, to determine if the title is installed on a computer, and if so, which version.
|
|
273
|
+
|
|
274
|
+
If the title does not install a .app bundle, or if the .app doesn't provide its version via the bundle id (e.g. Firefox) leave this blank, and provide a --version-script.
|
|
275
|
+
|
|
276
|
+
REQUIRED if --app-name is used.
|
|
277
|
+
ENDDESC
|
|
278
|
+
},
|
|
279
|
+
|
|
280
|
+
# @!attribute version_script
|
|
281
|
+
# @return [String] A script that will return the currently installed version of this
|
|
282
|
+
# title on a client mac
|
|
283
|
+
version_script: {
|
|
284
|
+
label: 'Version Script',
|
|
285
|
+
cli: :v,
|
|
286
|
+
# while the script is stored in the Title Editor as the extension attribute
|
|
287
|
+
# its handled differently, so we don't specify a ted_attribute here.
|
|
288
|
+
validate: true,
|
|
289
|
+
type: :string,
|
|
290
|
+
readline: :get_files,
|
|
291
|
+
changelog: true,
|
|
292
|
+
walkthru_na: :version_script_na,
|
|
293
|
+
invalid_msg: "Invalid Script Path. Local File must exist and start with '#!'.",
|
|
294
|
+
desc: <<~ENDDESC
|
|
295
|
+
If this title does NOT install a .app bundle, enter the local path to a script which will run on managed computers and output a <result> tag with the currently installed version of this title.
|
|
296
|
+
|
|
297
|
+
E.g. if version 1.2.3 is installed, the script should output the text:
|
|
298
|
+
<result>1.2.3</result>
|
|
299
|
+
and if no version of the title is installed, it should output:
|
|
300
|
+
<result></result>
|
|
301
|
+
|
|
302
|
+
NOTE: This cannot be used if --app-name & --app-bundle-id are used, but must be used if they are not
|
|
303
|
+
ENDDESC
|
|
304
|
+
},
|
|
305
|
+
|
|
306
|
+
# Whenever one of the groups listed is Xolo::TARGET_ALL ('all') then all other groups are
|
|
307
|
+
# ignored or deleted and the array contains only 'all'
|
|
308
|
+
#
|
|
309
|
+
# @!attribute release_groups
|
|
310
|
+
# @return [Array<String>] Jamf groups that will automatically get this title installed or
|
|
311
|
+
# updated when released
|
|
312
|
+
release_groups: {
|
|
313
|
+
label: 'Release Computer Groups',
|
|
314
|
+
cli: :r,
|
|
315
|
+
validate: true,
|
|
316
|
+
type: :string,
|
|
317
|
+
multi: true,
|
|
318
|
+
readline_prompt: 'Group Name',
|
|
319
|
+
changelog: true,
|
|
320
|
+
readline: :jamf_computer_group_names,
|
|
321
|
+
invalid_msg: 'Invalid release group(s). Must exist in Jamf and not be excluded.',
|
|
322
|
+
desc: <<~ENDDESC
|
|
323
|
+
One or more Jamf Computer Groups whose members will automatically have this title installed when new versions are released.
|
|
324
|
+
|
|
325
|
+
If your Xolo administrators allow it, you can use '#{Xolo::TARGET_ALL}' to auto-install on all computers that aren't excluded. If not, you'll be told how to request setting release groups to '#{Xolo::TARGET_ALL}'.
|
|
326
|
+
|
|
327
|
+
NOTE: Titles can always be installed manually (via command line or Self Service) on non-excluded computers. It's OK to have no release groups.
|
|
328
|
+
|
|
329
|
+
When using the --release-groups CLI option, you can specify more than one group by using the option more than once, or by providing a single option value with the groups separated by commas.
|
|
330
|
+
|
|
331
|
+
To remove all existing, use '#{Xolo::NONE}'.
|
|
332
|
+
|
|
333
|
+
NOTE: When a version is in 'pilot', before it is released, these groups are ignored, but instead a set of 'pilot' groups is defined for each version - and those groups will have that version auto-installed.
|
|
334
|
+
ENDDESC
|
|
335
|
+
},
|
|
336
|
+
|
|
337
|
+
# @!attribute excluded_groups
|
|
338
|
+
# @return [Array<String>] Jamf groups that are not allowed to install this title
|
|
339
|
+
excluded_groups: {
|
|
340
|
+
label: 'Excluded Computer Groups',
|
|
341
|
+
cli: :x,
|
|
342
|
+
validate: true,
|
|
343
|
+
type: :string,
|
|
344
|
+
multi: true,
|
|
345
|
+
changelog: true,
|
|
346
|
+
readline_prompt: 'Group Name',
|
|
347
|
+
readline: :jamf_computer_group_names,
|
|
348
|
+
invalid_msg: 'Invalid excluded computer group(s). Must exist in Jamf.',
|
|
349
|
+
desc: <<~ENDDESC
|
|
350
|
+
One or more Jamf Computer Groups whose members are not allowed to install this title.
|
|
351
|
+
|
|
352
|
+
When a computer is in one of these groups, the title is not available even if the computer is in a pilot or release group.
|
|
353
|
+
|
|
354
|
+
When using the --excluded-groups CLI option, you can specify more than one group by using the option more than once, or by providing a single option value with the groups separated by commas.
|
|
355
|
+
|
|
356
|
+
To remove all existing, use '#{Xolo::NONE}'.
|
|
357
|
+
|
|
358
|
+
NOTE: Regardless of the excluded groups set here, if the server has defined a 'forced_exclusion' in its config, that group is always excluded from all xolo titles. Also, computers that are 'frozen' for a title are excluded.
|
|
359
|
+
ENDDESC
|
|
360
|
+
},
|
|
361
|
+
|
|
362
|
+
# @!attribute uninstall_script
|
|
363
|
+
# @return [String] The path to a script starting with '#!' that will uninstall any version of
|
|
364
|
+
# this title.
|
|
365
|
+
uninstall_script: {
|
|
366
|
+
label: 'Uninstall Script',
|
|
367
|
+
cli: :U,
|
|
368
|
+
validate: true,
|
|
369
|
+
type: :string,
|
|
370
|
+
readline: :get_files,
|
|
371
|
+
walkthru_na: :uninstall_script_na,
|
|
372
|
+
changelog: true,
|
|
373
|
+
invalid_msg: "Invalid Script Path. Local File must exist and start with '#!'.",
|
|
374
|
+
desc: <<~ENDDESC
|
|
375
|
+
By default, Xolo cannot un-install a title. To make it do so you must provide either --uninstall-script or --uninstall-ids.
|
|
376
|
+
|
|
377
|
+
When using --uninstall-script, provide a path to a local file containing a script (starting with '#!') that will uninstall any version of this title.
|
|
378
|
+
|
|
379
|
+
This is useful when the publisher provides a custom uninstaller, or to uninstall things that were not installed via .pkg files (e.g. drag-installs).
|
|
380
|
+
|
|
381
|
+
Either --uninstall-script or --uninstall-ids must be provided if you want to set --expiration.
|
|
382
|
+
|
|
383
|
+
Use '#{Xolo::NONE}' to unset this,
|
|
384
|
+
ENDDESC
|
|
385
|
+
},
|
|
386
|
+
|
|
387
|
+
# @!attribute uninstall_ids
|
|
388
|
+
# @return [String] One or more package identifiers recognized by pkgutil, that will uninstall the
|
|
389
|
+
# currently installed version of if this title.
|
|
390
|
+
uninstall_ids: {
|
|
391
|
+
label: 'Uninstall IDs',
|
|
392
|
+
cli: :u,
|
|
393
|
+
validate: true,
|
|
394
|
+
type: :string,
|
|
395
|
+
multi: true,
|
|
396
|
+
multi_prompt: 'Pkg ID',
|
|
397
|
+
walkthru_na: :uninstall_ids_na,
|
|
398
|
+
changelog: true,
|
|
399
|
+
invalid_msg: 'Invalid uninstall ids',
|
|
400
|
+
desc: <<~ENDDESC
|
|
401
|
+
By default, Xolo cannot un-install a title. To make it do so you must provide either --uninstall-ids or --uninstall-script.
|
|
402
|
+
|
|
403
|
+
When using --uninstall-ids, provide one or more package identifiers, as listed by `pkgutil --pkgs`.
|
|
404
|
+
Xolo will use them to create a Jamf Script that will delete all the files that were installed by the matching .pkg installers.
|
|
405
|
+
|
|
406
|
+
NOTE: Package IDs will not work if the item was installed without using an installer.pkg
|
|
407
|
+
(e.g. drag-installing)
|
|
408
|
+
|
|
409
|
+
Either --uninstall-script or --uninstall-ids must be provided if you want to set --expiration.
|
|
410
|
+
|
|
411
|
+
When using the --uninstall-ids CLI option, you can specify more than one ID by using the option more than once, or by providing a single option value with the IDs separated by commas.
|
|
412
|
+
|
|
413
|
+
Use '#{Xolo::NONE}' to unset this,
|
|
414
|
+
ENDDESC
|
|
415
|
+
},
|
|
416
|
+
|
|
417
|
+
# @!attribute expiration
|
|
418
|
+
# @return [Integer] Number of days of disuse before the title is uninstalled.
|
|
419
|
+
expiration: {
|
|
420
|
+
label: 'Expire Days',
|
|
421
|
+
cli: :e,
|
|
422
|
+
validate: true,
|
|
423
|
+
type: :integer,
|
|
424
|
+
walkthru_na: :expiration_na,
|
|
425
|
+
changelog: true,
|
|
426
|
+
invalid_msg: "Invalid expiration. Must be a non-negative integer, or zero or '#{Xolo::NONE}' for no expiration.",
|
|
427
|
+
desc: <<~ENDDESC
|
|
428
|
+
Automatically uninstall this title if none of the items listed as '--expire-paths' have been opened in this number of days.
|
|
429
|
+
This can be useful for reclaiming unused licenses, especially if users can re-install as needed via Self Service.
|
|
430
|
+
|
|
431
|
+
IMPORTANT:
|
|
432
|
+
- This title must have an '--uninstall-method' set, or it can't be uninstalled by xolo
|
|
433
|
+
- You must define one or more --expire-paths
|
|
434
|
+
|
|
435
|
+
Setting this to '#{Xolo::NONE}' or zero, means 'do not expire'.
|
|
436
|
+
ENDDESC
|
|
437
|
+
},
|
|
438
|
+
|
|
439
|
+
# @!attribute expire_paths
|
|
440
|
+
# @return [Array<String>] App names that are considered to be 'used' if they spend any time
|
|
441
|
+
# in the foreground.
|
|
442
|
+
expire_paths: {
|
|
443
|
+
label: 'Expiration Paths',
|
|
444
|
+
cli: :E,
|
|
445
|
+
validate: true,
|
|
446
|
+
type: :string,
|
|
447
|
+
multi: true,
|
|
448
|
+
walkthru_na: :expiration_paths_na,
|
|
449
|
+
changelog: true,
|
|
450
|
+
readline: :get_files,
|
|
451
|
+
readline_prompt: 'Path',
|
|
452
|
+
invalid_msg: 'Invalid expiration paths. Must be absolute paths starting with /',
|
|
453
|
+
desc: <<~ENDDESC
|
|
454
|
+
The full paths to one or items (e.g. '/Applications/Google Chrome.app') that must be opened within the --expiration period to prevent automatic uninstall of the title. The paths need not be .apps, but can be anything. If the item at the path has never been opened, its date-added is used. If it doesn't exist, it is considered to never have been opened.
|
|
455
|
+
|
|
456
|
+
If multiple paths are specified, any one of them being opened will count. This is useful for multi-app titles, such as Microsoft Office, or when different versions have different app names.
|
|
457
|
+
|
|
458
|
+
When using the --expiration-paths CLI option, you can specify more than one path by using the option more than once, or by providing a single option value with the paths separated by commas.
|
|
459
|
+
ENDDESC
|
|
460
|
+
},
|
|
461
|
+
|
|
462
|
+
# @!attribute self_service
|
|
463
|
+
# @return [Boolean] Does this title appear in Self Service?
|
|
464
|
+
self_service: {
|
|
465
|
+
label: 'In Self Service?',
|
|
466
|
+
cli: :s,
|
|
467
|
+
type: :boolean,
|
|
468
|
+
validate: :validate_boolean,
|
|
469
|
+
default: false,
|
|
470
|
+
changelog: true,
|
|
471
|
+
walkthru_na: :ssvc_na,
|
|
472
|
+
desc: <<~ENDDESC
|
|
473
|
+
Make this title available in Self Service. Only the currently released version will be available.
|
|
474
|
+
|
|
475
|
+
While in pilot, a version is installed via its auto-install policy,
|
|
476
|
+
or 'sudo xolo install <title> <version>' or updated via its Patch Policy.
|
|
477
|
+
|
|
478
|
+
It will never be available to excluded computers.
|
|
479
|
+
|
|
480
|
+
Self Service is not available for titles with the release_group 'all'.
|
|
481
|
+
ENDDESC
|
|
482
|
+
},
|
|
483
|
+
|
|
484
|
+
# @!attribute self_service_category
|
|
485
|
+
# @return [String] The main Self Service category in which to show this title
|
|
486
|
+
self_service_category: {
|
|
487
|
+
label: 'Self Service Category',
|
|
488
|
+
cli: :c,
|
|
489
|
+
validate: true,
|
|
490
|
+
type: :string,
|
|
491
|
+
walkthru_na: :ssvc_na,
|
|
492
|
+
changelog: true,
|
|
493
|
+
readline: :jamf_category_names,
|
|
494
|
+
invalid_msg: 'Invalid category. Must exist in Jamf Pro.',
|
|
495
|
+
desc: <<~ENDDESC
|
|
496
|
+
The Category in which to display this title in Self Service.
|
|
497
|
+
REQUIRED if self_service is true, ignored otherwise
|
|
498
|
+
ENDDESC
|
|
499
|
+
},
|
|
500
|
+
|
|
501
|
+
# NOTE: This isn't stored anywhere after its used. If it is provided via
|
|
502
|
+
# xadm add-title or edit-title, it will be uploaded and applied at that
|
|
503
|
+
# time, but then if you fetch the title again, this value will be nil.
|
|
504
|
+
#
|
|
505
|
+
# @!attribute self_service_icon
|
|
506
|
+
# @return [String] Path to a local image file to use as the Self Service icon for this title.
|
|
507
|
+
self_service_icon: {
|
|
508
|
+
label: 'Self Service Icon',
|
|
509
|
+
cli: :i,
|
|
510
|
+
validate: true,
|
|
511
|
+
type: :string,
|
|
512
|
+
readline: :get_files,
|
|
513
|
+
changelog: true,
|
|
514
|
+
walkthru_na: :ssvc_na,
|
|
515
|
+
invalid_msg: 'Invalid Icon. Must exist locally and be a PNG, JPG, or GIF file.',
|
|
516
|
+
desc: <<~ENDDESC
|
|
517
|
+
Path to a local image file to use as the icon for this title in Self Service.
|
|
518
|
+
The file must be a PNG, JPG, or GIF file. The recommended size is 512x512 pixels.
|
|
519
|
+
If one has already been set, this will replace it.
|
|
520
|
+
ENDDESC
|
|
521
|
+
},
|
|
522
|
+
|
|
523
|
+
# @!attribute contact_email
|
|
524
|
+
# @return [String] Email address for the person or team responsible for this title
|
|
525
|
+
contact_email: {
|
|
526
|
+
label: 'Contact Email Address',
|
|
527
|
+
cli: :m,
|
|
528
|
+
required: true,
|
|
529
|
+
validate: true,
|
|
530
|
+
type: :string,
|
|
531
|
+
changelog: true,
|
|
532
|
+
invalid_msg: 'Invalid Email address.',
|
|
533
|
+
desc: <<~ENDDESC
|
|
534
|
+
The email address of the team or person responsible for this title. Used for notifications, questions, etc.
|
|
535
|
+
|
|
536
|
+
A mailing list for a team is preferable to an individual's email address, since individuals may leave the team.
|
|
537
|
+
ENDDESC
|
|
538
|
+
},
|
|
539
|
+
|
|
540
|
+
# @!attribute created_by
|
|
541
|
+
# @return [String] The login of the admin who created this title
|
|
542
|
+
created_by: {
|
|
543
|
+
label: 'Created By',
|
|
544
|
+
type: :string,
|
|
545
|
+
cli: false,
|
|
546
|
+
read_only: true, # maintained by the server, not editable by xadm TODO: same as cli: false??
|
|
547
|
+
desc: <<~ENDDESC
|
|
548
|
+
The login of the admin who created this title.
|
|
549
|
+
ENDDESC
|
|
550
|
+
},
|
|
551
|
+
|
|
552
|
+
# @!attribute creation_date
|
|
553
|
+
# @return [Time] The date this title was created.
|
|
554
|
+
creation_date: {
|
|
555
|
+
label: 'Creation Date',
|
|
556
|
+
type: :time,
|
|
557
|
+
cli: false,
|
|
558
|
+
read_only: true, # maintained by the server, not editable by xadm
|
|
559
|
+
desc: <<~ENDDESC
|
|
560
|
+
The date this title was created.
|
|
561
|
+
ENDDESC
|
|
562
|
+
},
|
|
563
|
+
|
|
564
|
+
# @!attribute modified_by
|
|
565
|
+
# @return [String] The login of the admin who last modified this title
|
|
566
|
+
modified_by: {
|
|
567
|
+
label: 'Modified By',
|
|
568
|
+
type: :string,
|
|
569
|
+
cli: false,
|
|
570
|
+
read_only: true, # maintained by the server, not editable by xadm
|
|
571
|
+
desc: <<~ENDDESC
|
|
572
|
+
The login of the admin who last modified this title.
|
|
573
|
+
ENDDESC
|
|
574
|
+
},
|
|
575
|
+
|
|
576
|
+
# @!attribute modification_date
|
|
577
|
+
# @return [Time] The date this title was last modified.
|
|
578
|
+
modification_date: {
|
|
579
|
+
label: 'Modification Date',
|
|
580
|
+
type: :time,
|
|
581
|
+
cli: false,
|
|
582
|
+
read_only: true, # maintained by the server, not editable by xadm
|
|
583
|
+
desc: <<~ENDDESC
|
|
584
|
+
The date this title was last modified.
|
|
585
|
+
ENDDESC
|
|
586
|
+
},
|
|
587
|
+
|
|
588
|
+
# @!attribute version_order
|
|
589
|
+
# @return [Array<String>] The known versions, newest to oldest
|
|
590
|
+
version_order: {
|
|
591
|
+
label: 'Versions',
|
|
592
|
+
type: :string,
|
|
593
|
+
multi: true,
|
|
594
|
+
cli: false,
|
|
595
|
+
read_only: true, # maintained by the server, not editable by xadm
|
|
596
|
+
desc: <<~ENDDESC
|
|
597
|
+
The known versions of the title, newest to oldest
|
|
598
|
+
ENDDESC
|
|
599
|
+
},
|
|
600
|
+
|
|
601
|
+
# @!attribute released_version
|
|
602
|
+
# @return [String] The currently released version, if any
|
|
603
|
+
released_version: {
|
|
604
|
+
label: 'Released Version',
|
|
605
|
+
type: :string,
|
|
606
|
+
cli: false,
|
|
607
|
+
changelog: true,
|
|
608
|
+
read_only: true, # maintained by the server, not editable by xadm
|
|
609
|
+
desc: <<~ENDDESC
|
|
610
|
+
The currently released version
|
|
611
|
+
ENDDESC
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
}.freeze
|
|
615
|
+
|
|
616
|
+
ATTRIBUTES.each_key do |attr|
|
|
617
|
+
attr_accessor attr
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
# Constructor
|
|
621
|
+
######################
|
|
622
|
+
######################
|
|
623
|
+
|
|
624
|
+
def initialize(data_hash)
|
|
625
|
+
super
|
|
626
|
+
# zero means no expiration
|
|
627
|
+
@expiration = nil if @expiration.to_i.zero?
|
|
628
|
+
end
|
|
629
|
+
|
|
630
|
+
# Instance Methods
|
|
631
|
+
######################
|
|
632
|
+
######################
|
|
633
|
+
|
|
634
|
+
# the latest version of this title in Xolo
|
|
635
|
+
# @param cnx [Faraday::Connection] The connection to use, must be logged in already
|
|
636
|
+
# @return [String]
|
|
637
|
+
####################
|
|
638
|
+
def latest_version
|
|
639
|
+
version_order&.first
|
|
640
|
+
end
|
|
641
|
+
|
|
642
|
+
end # class Title
|
|
643
|
+
|
|
644
|
+
end # module BaseClasses
|
|
645
|
+
|
|
646
|
+
end # module Core
|
|
647
|
+
|
|
648
|
+
end # module Xolo
|