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,52 @@
|
|
|
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
|
+
module Xolo
|
|
9
|
+
|
|
10
|
+
module Core
|
|
11
|
+
|
|
12
|
+
module Exceptions
|
|
13
|
+
|
|
14
|
+
# General errors
|
|
15
|
+
|
|
16
|
+
class MissingDataError < RuntimeError; end
|
|
17
|
+
|
|
18
|
+
class InvalidDataError < RuntimeError; end
|
|
19
|
+
|
|
20
|
+
class NoSuchItemError < RuntimeError; end
|
|
21
|
+
|
|
22
|
+
class UnsupportedError < RuntimeError; end
|
|
23
|
+
|
|
24
|
+
class KeychainError < RuntimeError; end
|
|
25
|
+
|
|
26
|
+
class ActionRequiredError < RuntimeError; end
|
|
27
|
+
|
|
28
|
+
# Connections & Access
|
|
29
|
+
|
|
30
|
+
class ConnectionError < RuntimeError; end
|
|
31
|
+
|
|
32
|
+
class NotConnectedError < ConnectionError; end
|
|
33
|
+
|
|
34
|
+
class TimeoutError < ConnectionError; end
|
|
35
|
+
|
|
36
|
+
class AuthenticationError < ConnectionError; end
|
|
37
|
+
|
|
38
|
+
class PermissionError < ConnectionError; end
|
|
39
|
+
|
|
40
|
+
class InvalidTokenError < ConnectionError; end
|
|
41
|
+
|
|
42
|
+
class ServerError < ConnectionError; end
|
|
43
|
+
|
|
44
|
+
# Parsing errors
|
|
45
|
+
|
|
46
|
+
class DisallowedYAMLDumpClass; end
|
|
47
|
+
|
|
48
|
+
end # module Exceptions
|
|
49
|
+
|
|
50
|
+
end # module Core
|
|
51
|
+
|
|
52
|
+
end # module Xolo
|
|
@@ -0,0 +1,43 @@
|
|
|
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
|
+
# constants and methods for consistent JSON processing on the server
|
|
16
|
+
module JSONWrappers
|
|
17
|
+
|
|
18
|
+
# when this module is extended
|
|
19
|
+
def self.extended(extender)
|
|
20
|
+
Xolo.verbose_extend extender, self
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# when this module is included
|
|
24
|
+
def self.included(includer)
|
|
25
|
+
Xolo.verbose_include includer, self
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# A wrapper for JSON.parse that always uses :symbolize_names
|
|
29
|
+
# def self.parse_json(str)
|
|
30
|
+
# JSON.parse str, symbolize_names: true
|
|
31
|
+
# end
|
|
32
|
+
|
|
33
|
+
# A wrapper for JSON.parse that always uses :symbolize_names
|
|
34
|
+
# and ensures UTF-8 encoding
|
|
35
|
+
def parse_json(str)
|
|
36
|
+
JSON.parse str.force_encoding('UTF-8'), symbolize_names: true
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
end # JSON
|
|
40
|
+
|
|
41
|
+
end # Core
|
|
42
|
+
|
|
43
|
+
end # module Xolo
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
# frozen_string_literal: true
|
|
8
|
+
|
|
9
|
+
module Xolo
|
|
10
|
+
|
|
11
|
+
module Core
|
|
12
|
+
|
|
13
|
+
module Loading
|
|
14
|
+
|
|
15
|
+
# touch this file to make mixins send text to stderr as things load
|
|
16
|
+
# or get mixed in
|
|
17
|
+
VERBOSE_LOADING_FILE = Pathname.new('/tmp/xolo-verbose-loading')
|
|
18
|
+
|
|
19
|
+
# Or, set this ENV var to also make mixins send text to stderr
|
|
20
|
+
VERBOSE_LOADING_ENV = 'XOLO_VERBOSE_LOADING'
|
|
21
|
+
|
|
22
|
+
def self.extended(extender)
|
|
23
|
+
Xolo.verbose_extend extender, self
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
# Only look at the filesystem once.
|
|
27
|
+
def verbose_loading?
|
|
28
|
+
return @verbose_loading unless @verbose_loading.nil?
|
|
29
|
+
|
|
30
|
+
@verbose_loading = VERBOSE_LOADING_FILE.file?
|
|
31
|
+
@verbose_loading ||= ENV.include? VERBOSE_LOADING_ENV
|
|
32
|
+
@verbose_loading
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
# Send a message to stderr if verbose loading is enabled
|
|
36
|
+
def load_msg(msg)
|
|
37
|
+
warn msg if verbose_loading?
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Mention that a module is being included into something
|
|
41
|
+
def verbose_include(includer, includee)
|
|
42
|
+
load_msg "--> #{includer} is including #{includee}"
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
# Mention that a module is being extended into something
|
|
46
|
+
def verbose_extend(extender, extendee)
|
|
47
|
+
load_msg "--> #{extender} is extending #{extendee}"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# Mention that a module is being extended into something
|
|
51
|
+
def verbose_inherit(child_class, parent_class)
|
|
52
|
+
load_msg "--> #{child_class} is a Subclass inheriting from #{parent_class}"
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
end # module
|
|
56
|
+
|
|
57
|
+
end # module
|
|
58
|
+
|
|
59
|
+
end # module Xolo
|
|
@@ -0,0 +1,292 @@
|
|
|
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
|
+
# frozen_string_literal: true
|
|
8
|
+
|
|
9
|
+
require 'io/console'
|
|
10
|
+
|
|
11
|
+
module Xolo
|
|
12
|
+
|
|
13
|
+
module Core
|
|
14
|
+
|
|
15
|
+
# Methods for formattng and sending output to stdout
|
|
16
|
+
# Should be included in classes as needed
|
|
17
|
+
#
|
|
18
|
+
# NOTE: Help output is auto-generated by 'optimist'
|
|
19
|
+
# The methods here are mostly for presenting info like
|
|
20
|
+
# columnizd lists and reports and the like.
|
|
21
|
+
module Output
|
|
22
|
+
|
|
23
|
+
# Constants
|
|
24
|
+
#############################
|
|
25
|
+
#############################
|
|
26
|
+
|
|
27
|
+
# This is used when we are not outputting to a terminal
|
|
28
|
+
# usually we're being piped or not running in a terminal
|
|
29
|
+
# so the lines should be as long as they want
|
|
30
|
+
DEFAULT_LINE_WIDTH = 2000
|
|
31
|
+
|
|
32
|
+
# Module methods
|
|
33
|
+
#
|
|
34
|
+
# These are available as module methods but not as 'helper'
|
|
35
|
+
# methods in sinatra routes & views.
|
|
36
|
+
#
|
|
37
|
+
##############################
|
|
38
|
+
##############################
|
|
39
|
+
|
|
40
|
+
# when this module is included
|
|
41
|
+
##############################
|
|
42
|
+
def self.included(includer)
|
|
43
|
+
Xolo.verbose_include includer, self
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# when this module is extended
|
|
47
|
+
def self.extended(extender)
|
|
48
|
+
Xolo.verbose_extend extender, self
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
# Instance methods
|
|
52
|
+
#
|
|
53
|
+
# These are available directly in sinatra routes and views
|
|
54
|
+
#
|
|
55
|
+
##############################
|
|
56
|
+
##############################
|
|
57
|
+
|
|
58
|
+
# @return [Integer] how many rows high is our terminal?
|
|
59
|
+
#########################
|
|
60
|
+
def terminal_height
|
|
61
|
+
IO.console.winsize.first
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# @return [Integer] how many columns wide is our terminal?
|
|
65
|
+
#########################
|
|
66
|
+
def terminal_width
|
|
67
|
+
IO.console.winsize.last
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# @return [Integer] how wide is our word wrap? terminal-width minus 5
|
|
71
|
+
#########################
|
|
72
|
+
def terminal_word_wrap
|
|
73
|
+
@terminal_word_wrap ||= terminal_width - 5
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# format a multi-line value by prepending the desired indentation
|
|
77
|
+
# to all but the first line, which is expected to be indented in-place where
|
|
78
|
+
# its being used.
|
|
79
|
+
#
|
|
80
|
+
# @param value [String] the value to format
|
|
81
|
+
# @param indent [Integer] the number of spaces to indent all but the first line
|
|
82
|
+
# @return [String] the formatted value
|
|
83
|
+
#######################
|
|
84
|
+
def format_multiline_indent(value, indent:)
|
|
85
|
+
value = value.to_s
|
|
86
|
+
return value unless value.include? "\n"
|
|
87
|
+
|
|
88
|
+
lines = value.split("\n")
|
|
89
|
+
lines[1..-1].each { |line| line.prepend ' ' * indent }
|
|
90
|
+
lines.join("\n")
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# TODO: Move this out of Xolo::Core
|
|
94
|
+
# Display a list of items in as many columns as possible
|
|
95
|
+
# based on terminal width, e.g. with 3 cols:
|
|
96
|
+
#
|
|
97
|
+
# a thing another thing third thing
|
|
98
|
+
# thing2 line2 thing third line 2
|
|
99
|
+
# line3 thing another one and yet a 3rd
|
|
100
|
+
# oh my line4 4 line ok? yes, this is it
|
|
101
|
+
#
|
|
102
|
+
# and if the list is longer than terminal height,
|
|
103
|
+
# pipe it through 'less'
|
|
104
|
+
#
|
|
105
|
+
# @param header [String] A string to display at the top prepended with a '#'
|
|
106
|
+
# and appended with a newline and a line of ######'s of the same length.
|
|
107
|
+
#
|
|
108
|
+
# @param list [Array<String>] the items to list
|
|
109
|
+
#
|
|
110
|
+
# @return [void]
|
|
111
|
+
############################
|
|
112
|
+
def list_in_cols(header, list)
|
|
113
|
+
longest_list_item = list.map(&:size).max
|
|
114
|
+
use_columns = (longest_list_item + 5) < terminal_width
|
|
115
|
+
|
|
116
|
+
list_to_display = use_columns ? highline_cli.list(list, :columns_down) : list.join("\n")
|
|
117
|
+
|
|
118
|
+
output = +"# #{header}\n"
|
|
119
|
+
output << '#' * (terminal_width - 5)
|
|
120
|
+
output << "\n"
|
|
121
|
+
output << list_to_display
|
|
122
|
+
|
|
123
|
+
show_text output
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# Generate a report of rowed/columned data, either fixed-width or tab-delimited.
|
|
127
|
+
#
|
|
128
|
+
# Title and header lines are pre-pended with '# ' for easier exclusion
|
|
129
|
+
# when using the report as input for some other program.
|
|
130
|
+
# If the :type is :fixed, so will the column header line.
|
|
131
|
+
# (however, for parsing this data, try using the --json option)
|
|
132
|
+
#
|
|
133
|
+
# @param lines [Array<Array>] the rows and columns of data
|
|
134
|
+
#
|
|
135
|
+
# @param type [Symbol] :fixed or :tab, defaults to :fixed
|
|
136
|
+
#
|
|
137
|
+
# @params title [String] a descriptive text or title, shown above the
|
|
138
|
+
# column headers. Every line is pre-pended with '# '.
|
|
139
|
+
# Only used on :fixed reports.
|
|
140
|
+
#
|
|
141
|
+
# @params header_row [Array<String>] the column headers. optional.
|
|
142
|
+
#
|
|
143
|
+
# @return [String] the formatted report.
|
|
144
|
+
#
|
|
145
|
+
############################
|
|
146
|
+
def generate_report(lines, type: :fixed, header_row: [], title: nil)
|
|
147
|
+
return Xolo::BLANK if lines.pix_empty?
|
|
148
|
+
|
|
149
|
+
raise ArgumentError, 'The first argument must be an Array' unless lines.is_a?(Array)
|
|
150
|
+
raise ArgumentError, 'The header_row must be an Array' unless header_row.is_a? Array
|
|
151
|
+
|
|
152
|
+
# tab delim is easy
|
|
153
|
+
if type == :tab
|
|
154
|
+
report_tab = header_row.join("\t")
|
|
155
|
+
lines.each { |line| report_tab += "\n#{line.join("\t")}" }
|
|
156
|
+
return report_tab.strip
|
|
157
|
+
end # if :tab
|
|
158
|
+
|
|
159
|
+
# below here, fixed width
|
|
160
|
+
|
|
161
|
+
line_width, format_str = width_and_format(lines, header_row)
|
|
162
|
+
|
|
163
|
+
# title if given
|
|
164
|
+
report = title ? +"# #{title}\n" : +''
|
|
165
|
+
|
|
166
|
+
unless header_row.empty?
|
|
167
|
+
unless header_row.size == lines[0].size
|
|
168
|
+
raise ArgumentError,
|
|
169
|
+
"Header row must have #{lines[0].count} items"
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
# then the header line if given
|
|
173
|
+
report += format_str % header_row
|
|
174
|
+
# add a separator
|
|
175
|
+
report += '#' + ('-' * (line_width - 1)) + "\n"
|
|
176
|
+
end
|
|
177
|
+
# add the rows
|
|
178
|
+
lines.each { |line| report += format_str % line }
|
|
179
|
+
|
|
180
|
+
report
|
|
181
|
+
end # generate report
|
|
182
|
+
|
|
183
|
+
# Given an Array of Arrays representing rows and columns of data,
|
|
184
|
+
# figure out the appropriate line-width for the longest line
|
|
185
|
+
# and the printf format string to create the columns
|
|
186
|
+
#
|
|
187
|
+
#
|
|
188
|
+
# @param lines [Array<Array>] The rows and columns of data
|
|
189
|
+
#
|
|
190
|
+
# @param header_row [Array] An optional header row to include in the
|
|
191
|
+
# width calculation.
|
|
192
|
+
#
|
|
193
|
+
# @return [Array<Integer, String>] the line width and format string
|
|
194
|
+
#
|
|
195
|
+
############################
|
|
196
|
+
def width_and_format(lines, header_row = [])
|
|
197
|
+
# below here, fixed width
|
|
198
|
+
format_str = +''
|
|
199
|
+
line_width = 0
|
|
200
|
+
header_row[0] = "# #{header_row[0]}"
|
|
201
|
+
|
|
202
|
+
col_widths(lines, header_row).each do |w|
|
|
203
|
+
# make sure there's a space between columns
|
|
204
|
+
col_width = w + 1
|
|
205
|
+
|
|
206
|
+
# add the column to the printf format
|
|
207
|
+
format_str += "%-#{col_width}s"
|
|
208
|
+
line_width += col_width
|
|
209
|
+
end
|
|
210
|
+
format_str += "\n"
|
|
211
|
+
|
|
212
|
+
# if needed, limit the total line width for the header the width of the terminal
|
|
213
|
+
max_width = $stdout.tty? ? terminal_word_wrap : DEFAULT_LINE_WIDTH
|
|
214
|
+
line_width = max_width if line_width > max_width
|
|
215
|
+
|
|
216
|
+
[line_width, format_str]
|
|
217
|
+
end
|
|
218
|
+
|
|
219
|
+
# Given an Array of Arrays representing rows and columns of data
|
|
220
|
+
# figure out the widest width of each column and return an array
|
|
221
|
+
# of integers representing those widths
|
|
222
|
+
#
|
|
223
|
+
# @param data [Array<Array>] The rows and columns of data
|
|
224
|
+
#
|
|
225
|
+
# @param header_row [Array] An optional header row to include in the
|
|
226
|
+
# width calculation.
|
|
227
|
+
#
|
|
228
|
+
# @return [Array<Integer>] the max widths of each column of data.
|
|
229
|
+
#
|
|
230
|
+
############################
|
|
231
|
+
def col_widths(data, header_row = [])
|
|
232
|
+
widths = header_row.map { |c| c.to_s.length }
|
|
233
|
+
data.each do |row|
|
|
234
|
+
row.each_index do |col|
|
|
235
|
+
this_width = row[col].to_s.length
|
|
236
|
+
widths[col] = this_width if this_width > widths[col].to_i
|
|
237
|
+
end # do field
|
|
238
|
+
end # do line
|
|
239
|
+
widths
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
# Should a given string be displayed via /usr/bin/less?
|
|
243
|
+
# true if stdout is a tty AND the string is > (terminal height - 2)
|
|
244
|
+
# The - 2 accounts for the final newline and an extra line at the
|
|
245
|
+
# bottom of the terminal, for better visual results
|
|
246
|
+
#########################
|
|
247
|
+
def use_less?(text)
|
|
248
|
+
$stdout.tty? && text.lines.size > (terminal_height - 2)
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
# Send a string to the terminal, possibly piping it through 'less'
|
|
252
|
+
# if the number of lines is greater than the number of terminal lines
|
|
253
|
+
#
|
|
254
|
+
# @param text[String] the text to send to the terminal
|
|
255
|
+
#
|
|
256
|
+
# @param show_help[Boolean] should the text have a line at the top
|
|
257
|
+
# showing basic 'less' key commands.
|
|
258
|
+
#
|
|
259
|
+
# @result [void]
|
|
260
|
+
#
|
|
261
|
+
############################
|
|
262
|
+
def show_text(text, show_help = true)
|
|
263
|
+
unless use_less?(text)
|
|
264
|
+
puts text
|
|
265
|
+
return
|
|
266
|
+
end
|
|
267
|
+
|
|
268
|
+
if show_help
|
|
269
|
+
help = "# -- Using /usr/bin/less: ' ' next, 'b' prev, 'q' exit, 'h' help --"
|
|
270
|
+
text = "#{help}\n#{text}"
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
# point stdout through less, print, then restore stdout
|
|
274
|
+
less = IO.popen('/usr/bin/less', 'w')
|
|
275
|
+
|
|
276
|
+
begin
|
|
277
|
+
less.puts text
|
|
278
|
+
|
|
279
|
+
# this catches the quitting of 'less' before all the output
|
|
280
|
+
# is displayed
|
|
281
|
+
rescue Errno::EPIPE
|
|
282
|
+
true
|
|
283
|
+
ensure
|
|
284
|
+
less&.close
|
|
285
|
+
end
|
|
286
|
+
end
|
|
287
|
+
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
end
|
|
291
|
+
|
|
292
|
+
end # module
|
|
@@ -0,0 +1,21 @@
|
|
|
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
|
+
# main module
|
|
9
|
+
module Xolo
|
|
10
|
+
|
|
11
|
+
module Core
|
|
12
|
+
|
|
13
|
+
module Version
|
|
14
|
+
|
|
15
|
+
VERSION = '1.0.1'.freeze
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
end # module
|
data/lib/xolo/core.rb
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
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
|
+
# frozen_string_literal: true
|
|
8
|
+
|
|
9
|
+
# Load the core xolo functionality
|
|
10
|
+
#
|
|
11
|
+
# This is done automatically when you `require 'xolo/admin'` or
|
|
12
|
+
# `require 'xolo/server'`
|
|
13
|
+
|
|
14
|
+
# Ruby Standard Libraries
|
|
15
|
+
######
|
|
16
|
+
require 'English'
|
|
17
|
+
require 'date'
|
|
18
|
+
require 'time'
|
|
19
|
+
require 'pathname'
|
|
20
|
+
require 'json'
|
|
21
|
+
|
|
22
|
+
# Other Gems to include at this level
|
|
23
|
+
require 'pixar-ruby-extensions'
|
|
24
|
+
|
|
25
|
+
# Internal requires - order matters
|
|
26
|
+
require 'xolo/core/loading'
|
|
27
|
+
require 'xolo/core/version'
|
|
28
|
+
require 'xolo/core/constants'
|
|
29
|
+
require 'xolo/core/exceptions'
|
|
30
|
+
|
|
31
|
+
# The main module
|
|
32
|
+
module Xolo
|
|
33
|
+
|
|
34
|
+
extend Xolo::Core::Loading
|
|
35
|
+
include Xolo::Core::Version
|
|
36
|
+
include Xolo::Core::Constants
|
|
37
|
+
include Xolo::Core::Exceptions
|
|
38
|
+
|
|
39
|
+
end # module Xolo
|
|
40
|
+
|
|
41
|
+
require 'xolo/core/json_wrappers'
|
|
42
|
+
require 'xolo/core/base_classes/configuration'
|
|
43
|
+
require 'xolo/core/base_classes/server_object'
|
|
44
|
+
require 'xolo/core/base_classes/title'
|
|
45
|
+
require 'xolo/core/base_classes/version'
|
|
46
|
+
require 'xolo/core/output'
|
|
@@ -395,7 +395,6 @@ module Xolo
|
|
|
395
395
|
# @!attribute jamf_gui_hostname
|
|
396
396
|
# @return [String] The hostname of the Jamf Pro server used for links to the GUI webapp
|
|
397
397
|
jamf_gui_hostname: {
|
|
398
|
-
required: true,
|
|
399
398
|
type: :string,
|
|
400
399
|
desc: <<~ENDDESC
|
|
401
400
|
The hostname of the Jamf Pro server used for links to the GUI webapp, if different from the jamf_hostname.
|
|
@@ -478,7 +477,7 @@ module Xolo
|
|
|
478
477
|
desc: <<~ENDDESC
|
|
479
478
|
The password for the username that connects to the Jamf Pro APIs.
|
|
480
479
|
|
|
481
|
-
If you start this value with a vertical bar '|', everything after the bar is a command to be executed by the server at start-time. The command must return the
|
|
480
|
+
If you start this value with a vertical bar '|', everything after the bar is a command to be executed by the server at start-time. The command must return the password to standard output. This is useful when using a secret-storage system to manage secrets.
|
|
482
481
|
|
|
483
482
|
If the value is a path to a readable file, the file's contents are used.
|
|
484
483
|
|
|
@@ -346,21 +346,16 @@ module Xolo
|
|
|
346
346
|
# @return [void]
|
|
347
347
|
################################
|
|
348
348
|
def configure_jamf_normal_ea
|
|
349
|
+
# nothing to do if its nil, if we need to delete it, that'll happen later
|
|
350
|
+
return if version_script_contents.pix_empty?
|
|
351
|
+
|
|
349
352
|
progress "Jamf: Configuring regular extension attribute '#{jamf_normal_ea_name}'", log: :info
|
|
350
353
|
|
|
351
354
|
jamf_normal_ea.description = "The version of xolo title '#{title}' installed on the machine"
|
|
352
|
-
jamf_normal_ea.data_type =
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
# nothing to do if its nil, if we need to delete it, that'll happen later
|
|
357
|
-
else
|
|
358
|
-
jamf_normal_ea.enabled = true
|
|
359
|
-
jamf_normal_ea.input_type = 'script'
|
|
360
|
-
jamf_normal_ea.script = version_script_contents
|
|
361
|
-
end
|
|
362
|
-
|
|
363
|
-
jamf_normal_ea.script = scr
|
|
355
|
+
jamf_normal_ea.data_type = 'String'
|
|
356
|
+
jamf_normal_ea.input_type = 'script'
|
|
357
|
+
jamf_normal_ea.enable
|
|
358
|
+
jamf_normal_ea.script = version_script_contents
|
|
364
359
|
jamf_normal_ea.save
|
|
365
360
|
end
|
|
366
361
|
|
|
@@ -86,8 +86,10 @@ module Xolo
|
|
|
86
86
|
sleep 2
|
|
87
87
|
|
|
88
88
|
# re-fetch the title from ted and enable it
|
|
89
|
+
progress "Title Editor: Enabling SoftwareTitle '#{title}'", log: :info
|
|
89
90
|
ted_title(refresh: true).enable
|
|
90
91
|
|
|
92
|
+
# cache the new title object id
|
|
91
93
|
self.ted_id_number = ted_title.softwareTitleId
|
|
92
94
|
end
|
|
93
95
|
|
|
@@ -197,6 +199,9 @@ module Xolo
|
|
|
197
199
|
# This will also apply the changes to all patch component criteria
|
|
198
200
|
apply_requirement_changes
|
|
199
201
|
|
|
202
|
+
# re-enable all patches, after any change, which might have disabled them
|
|
203
|
+
reenable_all_ted_patches
|
|
204
|
+
|
|
200
205
|
# mucking with the patches often disables the title, make sure its enabled.
|
|
201
206
|
enable_ted_title
|
|
202
207
|
|
|
@@ -416,6 +421,8 @@ module Xolo
|
|
|
416
421
|
#
|
|
417
422
|
# Re-enable the title in ted after updating any patches
|
|
418
423
|
#
|
|
424
|
+
# TODO: Now that we are using stub patches, do we need the loop?
|
|
425
|
+
#
|
|
419
426
|
# @return [void]
|
|
420
427
|
##############################
|
|
421
428
|
def enable_ted_title
|
|
@@ -430,10 +437,10 @@ module Xolo
|
|
|
430
437
|
loop do
|
|
431
438
|
raise Xolo::TimeoutError, "Title Editor: Timed out waiting for SoftwareTitle '#{title}' to enable" if Time.now > breaktime
|
|
432
439
|
|
|
433
|
-
sleep 5
|
|
434
440
|
ted_title(refresh: true).enable
|
|
435
441
|
break
|
|
436
442
|
rescue Windoo::MissingDataError => e
|
|
443
|
+
sleep 5
|
|
437
444
|
log_debug "Title Editor: Looping up to #{Xolo::Server::Constants::MAX_JAMF_WAIT_FOR_TITLE_EDITOR} secs while re-enabling SoftwareTitle '#{title}': #{e}"
|
|
438
445
|
|
|
439
446
|
# make sure all patches are enabled, even tho at least one should have been
|
|
@@ -500,16 +507,25 @@ module Xolo
|
|
|
500
507
|
if ted_title.patches.empty?
|
|
501
508
|
create_and_enable_stub_patch_in_ted(ted_title)
|
|
502
509
|
else
|
|
503
|
-
#
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
510
|
+
# repair all patches, because reparing the title might have changed the requirements
|
|
511
|
+
progress "Title Editor: Re-enabling all patches for '#{title}'", log: :info
|
|
512
|
+
version_objects.each do |vobj|
|
|
513
|
+
vobj.repair_ted_patch
|
|
507
514
|
end
|
|
508
515
|
end
|
|
509
516
|
|
|
510
517
|
ted_title.enable unless ted_title(refresh: true).enabled?
|
|
511
518
|
end
|
|
512
519
|
|
|
520
|
+
# Re-enable all patches in the title editor
|
|
521
|
+
# @return [void]
|
|
522
|
+
###########################
|
|
523
|
+
def reenable_all_ted_patches
|
|
524
|
+
# re-enable all patches, after any change, which might have disabled them
|
|
525
|
+
progress "Title Editor: Re-enabling all patches for '#{title}'", log: :info
|
|
526
|
+
version_objects.each { |vobj| vobj.enable_ted_patch }
|
|
527
|
+
end
|
|
528
|
+
|
|
513
529
|
end # TitleEditorTitle
|
|
514
530
|
|
|
515
531
|
end # Mixins
|