windoo 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 +7 -0
- data/CHANGES.md +9 -0
- data/LICENSE.txt +177 -0
- data/README.md +222 -0
- data/lib/windoo/base_classes/array_manager.rb +335 -0
- data/lib/windoo/base_classes/criteria_manager.rb +327 -0
- data/lib/windoo/base_classes/criterion.rb +226 -0
- data/lib/windoo/base_classes/json_object.rb +472 -0
- data/lib/windoo/configuration.rb +221 -0
- data/lib/windoo/connection/actions.rb +152 -0
- data/lib/windoo/connection/attributes.rb +156 -0
- data/lib/windoo/connection/connect.rb +402 -0
- data/lib/windoo/connection/constants.rb +55 -0
- data/lib/windoo/connection/token.rb +489 -0
- data/lib/windoo/connection.rb +92 -0
- data/lib/windoo/converters.rb +31 -0
- data/lib/windoo/exceptions.rb +34 -0
- data/lib/windoo/mixins/api_collection.rb +408 -0
- data/lib/windoo/mixins/constants.rb +43 -0
- data/lib/windoo/mixins/default_connection.rb +75 -0
- data/lib/windoo/mixins/immutable.rb +34 -0
- data/lib/windoo/mixins/loading.rb +38 -0
- data/lib/windoo/mixins/patch/component.rb +102 -0
- data/lib/windoo/mixins/software_title/extension_attribute.rb +106 -0
- data/lib/windoo/mixins/utility.rb +23 -0
- data/lib/windoo/objects/capability.rb +82 -0
- data/lib/windoo/objects/capability_manager.rb +52 -0
- data/lib/windoo/objects/component.rb +99 -0
- data/lib/windoo/objects/component_criteria_manager.rb +26 -0
- data/lib/windoo/objects/component_criterion.rb +66 -0
- data/lib/windoo/objects/extension_attribute.rb +149 -0
- data/lib/windoo/objects/kill_app.rb +92 -0
- data/lib/windoo/objects/kill_app_manager.rb +89 -0
- data/lib/windoo/objects/patch.rb +235 -0
- data/lib/windoo/objects/patch_manager.rb +240 -0
- data/lib/windoo/objects/requirement.rb +85 -0
- data/lib/windoo/objects/requirement_manager.rb +52 -0
- data/lib/windoo/objects/software_title.rb +407 -0
- data/lib/windoo/validate.rb +548 -0
- data/lib/windoo/version.rb +15 -0
- data/lib/windoo/zeitwerk_config.rb +158 -0
- data/lib/windoo.rb +56 -0
- metadata +141 -0
@@ -0,0 +1,408 @@
|
|
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
|
+
# main module
|
10
|
+
module Windoo
|
11
|
+
|
12
|
+
module Mixins
|
13
|
+
|
14
|
+
# This should be included into The TitleEditor and
|
15
|
+
# Admin classes that represent API collections in their
|
16
|
+
# respective servers.
|
17
|
+
#
|
18
|
+
# It defines core methods for dealing with such collections.
|
19
|
+
module APICollection
|
20
|
+
|
21
|
+
# when this module is included, also extend our Class Methods
|
22
|
+
def self.included(includer)
|
23
|
+
Windoo.verbose_include includer, self
|
24
|
+
includer.extend(ClassMethods)
|
25
|
+
end
|
26
|
+
|
27
|
+
# REQUIRED ITEMS WHEN MIXING IN
|
28
|
+
###################################
|
29
|
+
###################################
|
30
|
+
# Classes mixing in this module must define these things:
|
31
|
+
|
32
|
+
# Constant RSRC_PATH
|
33
|
+
######
|
34
|
+
# The path from which to GET, PUT, or DELETE
|
35
|
+
# lists or instances of this class. e.g 'patches'
|
36
|
+
# or 'softwaretitles'
|
37
|
+
|
38
|
+
# Constant CONTAINER_CLASS
|
39
|
+
######
|
40
|
+
# Except for softwaretitles, the POST/create path for
|
41
|
+
# all objects is under the path of their container object.
|
42
|
+
#
|
43
|
+
# e.g. to create a patch for a softwaretitle, the path is:
|
44
|
+
# .../softwaretitles/{id}/patches
|
45
|
+
#
|
46
|
+
# and to create a killapp in a patch, it is:
|
47
|
+
# .../patches/{id}/killapps
|
48
|
+
#
|
49
|
+
# This constant allows this class to calculate
|
50
|
+
# the POST path from its container's path, and gives
|
51
|
+
# access to other data from the container class.
|
52
|
+
|
53
|
+
# instance method #handle_create_response(post_response, container_id: nil)
|
54
|
+
######
|
55
|
+
#
|
56
|
+
# This method is called after a new object is created on the server,
|
57
|
+
# and the data from the POST response is passed in.
|
58
|
+
# This method should update the attributes with any new
|
59
|
+
# data from the result, such as modification dates, ids, etc.
|
60
|
+
#
|
61
|
+
# It must return the primary identifier of the new object
|
62
|
+
|
63
|
+
# instance method #handle_update_response(put_response)
|
64
|
+
######
|
65
|
+
#
|
66
|
+
# This method is called after an object is updated on the server,
|
67
|
+
# and the data from the PUT response is passed in.
|
68
|
+
# This method should update the attributes with any new
|
69
|
+
# data from the result, such as modification dates, etc.
|
70
|
+
#
|
71
|
+
# It must return the primary identifier of the updated object
|
72
|
+
|
73
|
+
###################################
|
74
|
+
###################################
|
75
|
+
|
76
|
+
# Class Methods
|
77
|
+
#####################################
|
78
|
+
module ClassMethods
|
79
|
+
|
80
|
+
####################
|
81
|
+
def self.extended(extender)
|
82
|
+
Windoo.verbose_extend extender, self
|
83
|
+
end
|
84
|
+
|
85
|
+
# Make a new instance on the server.
|
86
|
+
#
|
87
|
+
# The attributes marked as required must be supplied
|
88
|
+
# in the keyword args. Others may be included, or
|
89
|
+
# may be added later. To see the required args, use
|
90
|
+
# the .required_attributes class method
|
91
|
+
#
|
92
|
+
# @param container [Object] All objects other than SoftwareTitles
|
93
|
+
# are contained within other objects, and created via methods
|
94
|
+
# within those container objects. They will pass 'self'
|
95
|
+
#
|
96
|
+
# @param init_data [Hasn] The attributes of the new item as keyword
|
97
|
+
# arguments. Some may be required.
|
98
|
+
#
|
99
|
+
# @return [Object] A new instance of the class, already saved
|
100
|
+
# to the server.
|
101
|
+
#
|
102
|
+
####################
|
103
|
+
def create(container: nil, cnx: Windoo.cnx, **init_data)
|
104
|
+
container = Windoo::Validate.container_for_new_object(
|
105
|
+
new_object_class: self,
|
106
|
+
container: container
|
107
|
+
)
|
108
|
+
|
109
|
+
unless (required_attributes & init_data.keys) == required_attributes
|
110
|
+
raise ArgumentError,
|
111
|
+
"Missing one or more required attributes for #{self}: #{required_attributes.join ', '}"
|
112
|
+
end
|
113
|
+
|
114
|
+
# validate all init values
|
115
|
+
json_attributes.each do |attr_name, attr_def|
|
116
|
+
init_val = init_data[attr_name]
|
117
|
+
if attr_def[:required]
|
118
|
+
Windoo::Validate.not_nil(
|
119
|
+
init_val,
|
120
|
+
msg: "Value for #{attr_name}: must be provided"
|
121
|
+
)
|
122
|
+
end
|
123
|
+
|
124
|
+
init_data[attr_name] = Windoo::Validate.json_attr init_val, attr_def: attr_def, attr_name: attr_name
|
125
|
+
end
|
126
|
+
# add the container if applicable
|
127
|
+
init_data[:from_container] = container if container
|
128
|
+
|
129
|
+
# Let other steps in the process know we are being called from #create
|
130
|
+
init_data[:creating] = true
|
131
|
+
|
132
|
+
# Create our instance
|
133
|
+
obj = new(**init_data)
|
134
|
+
|
135
|
+
# create it on the server
|
136
|
+
obj.create_on_server cnx: cnx
|
137
|
+
|
138
|
+
# return it
|
139
|
+
obj
|
140
|
+
end
|
141
|
+
|
142
|
+
# Instantiate from the API directly.
|
143
|
+
# @return [Object]
|
144
|
+
#
|
145
|
+
####################
|
146
|
+
def fetch(primary_ident, cnx: Windoo.cnx)
|
147
|
+
if primary_ident.is_a? Hash
|
148
|
+
raise 'All API objects other than SoftwareTitle are fetched only by their id number'
|
149
|
+
end
|
150
|
+
|
151
|
+
init_data = cnx.get("#{self::RSRC_PATH}/#{primary_ident}")
|
152
|
+
init_data[:cnx] = cnx
|
153
|
+
init_data[:fetching] = true
|
154
|
+
new(**init_data)
|
155
|
+
end
|
156
|
+
|
157
|
+
# This is used by container classes to instantiate the objects they contain
|
158
|
+
# e.g. when when instantiating a Patch, it needs to instantiate
|
159
|
+
# killApps, components, and capabilites. it will do so with this method
|
160
|
+
#
|
161
|
+
####################
|
162
|
+
def instantiate_from_container(container:, **init_data)
|
163
|
+
container = Windoo::Validate.container_for_new_object(
|
164
|
+
new_object_class: self,
|
165
|
+
container: container
|
166
|
+
)
|
167
|
+
init_data[:from_container] = container
|
168
|
+
init_data[:cnx] = container.cnx
|
169
|
+
new(**init_data)
|
170
|
+
end
|
171
|
+
|
172
|
+
####
|
173
|
+
def delete(primary_ident, cnx: Windoo.cnx)
|
174
|
+
if primary_ident.is_a? Hash
|
175
|
+
raise ArgumentError, 'All API objects other than SoftwareTitle are deleted only by their id number'
|
176
|
+
end
|
177
|
+
|
178
|
+
cnx.delete("#{self::RSRC_PATH}/#{primary_ident}")
|
179
|
+
rescue Windoo::NoSuchItemError
|
180
|
+
# wasn't there to begin with
|
181
|
+
nil
|
182
|
+
end
|
183
|
+
|
184
|
+
end # module ClassMethods
|
185
|
+
|
186
|
+
# Constructor
|
187
|
+
######################
|
188
|
+
def initialize(**init_data)
|
189
|
+
fetching = init_data.delete :fetching
|
190
|
+
@cnx = init_data.delete :cnx
|
191
|
+
|
192
|
+
@container ||= init_data.delete :from_container
|
193
|
+
|
194
|
+
# we save 'creating' in an inst. var so we know to create
|
195
|
+
# rather than update later on when we #save
|
196
|
+
@creating = true if init_data[:creating]
|
197
|
+
|
198
|
+
unless fetching || @container || @creating
|
199
|
+
raise Windoo::UnsupportedError, "#{self.class} can only be instantiated using .fetch or .create, not .new"
|
200
|
+
end
|
201
|
+
|
202
|
+
super
|
203
|
+
end
|
204
|
+
|
205
|
+
# Public Instance Methods
|
206
|
+
####################
|
207
|
+
|
208
|
+
# @return [APICollection] The object that contains this object, or nil
|
209
|
+
# if nothing contains this object
|
210
|
+
# def container
|
211
|
+
# return @container if defined? @container
|
212
|
+
|
213
|
+
# @container =
|
214
|
+
# if defined? self.class::CONTAINER_CLASS
|
215
|
+
# container_id_key = self.class::CONTAINER_CLASS.primary_id_key
|
216
|
+
# container_id = send container_id_key
|
217
|
+
# self.class::CONTAINER_CLASS.fetch container_id
|
218
|
+
# end
|
219
|
+
# end
|
220
|
+
|
221
|
+
# @return [nil, Integer] our primary identifier value, regardless of its
|
222
|
+
# attribute name. Before creation, this is nil. After deletion, this is -1
|
223
|
+
#
|
224
|
+
####################
|
225
|
+
def primary_id
|
226
|
+
send self.class.primary_id_key
|
227
|
+
end
|
228
|
+
|
229
|
+
# @return [Boolean] Is this object the same as another, based on their
|
230
|
+
# primary_id
|
231
|
+
####################
|
232
|
+
def ==(other)
|
233
|
+
return false unless self.class == other.class
|
234
|
+
|
235
|
+
primary_id == other.primary_id
|
236
|
+
end
|
237
|
+
|
238
|
+
# @return [Integer] our primary identifier value before we were deleted.
|
239
|
+
# Before deletion, this is nil
|
240
|
+
#
|
241
|
+
####################
|
242
|
+
def deleted_id
|
243
|
+
@deleted_id
|
244
|
+
end
|
245
|
+
|
246
|
+
# @return [Integer] our primary identifier value before we were deleted.
|
247
|
+
# Before deletion, this is nil
|
248
|
+
#
|
249
|
+
####################
|
250
|
+
def deleted_id
|
251
|
+
@deleted_id
|
252
|
+
end
|
253
|
+
|
254
|
+
# @return [Windoo::APICollection] If this object is contained within another,
|
255
|
+
# then here is the object that contains it
|
256
|
+
####################
|
257
|
+
def container
|
258
|
+
@container
|
259
|
+
end
|
260
|
+
|
261
|
+
# @return [Windoo::Connection] The server connection for this object
|
262
|
+
####################
|
263
|
+
def cnx
|
264
|
+
@cnx
|
265
|
+
end
|
266
|
+
|
267
|
+
# @return [Windoo::SoftwareTitle] The SoftwareTitle object that ultimately
|
268
|
+
# contains this object
|
269
|
+
####################
|
270
|
+
def softwareTitle
|
271
|
+
return self if is_a? Windoo::SoftwareTitle
|
272
|
+
|
273
|
+
return container if container.is_a? Windoo::SoftwareTitle
|
274
|
+
|
275
|
+
container.softwareTitle
|
276
|
+
end
|
277
|
+
|
278
|
+
# Delete this object
|
279
|
+
#
|
280
|
+
# @return [Integer] The id of the object that was deleted
|
281
|
+
#
|
282
|
+
#############
|
283
|
+
def delete
|
284
|
+
self.class.delete primary_id, cnx: cnx
|
285
|
+
@deleted_id = primary_id
|
286
|
+
instance_variable_set "@#{self.class.primary_id_key}", -1
|
287
|
+
@deleted_id
|
288
|
+
end
|
289
|
+
|
290
|
+
# create a new object on the server from this instance
|
291
|
+
#
|
292
|
+
# @param container_id [Integer, nil] the id of the object that will
|
293
|
+
# contain the one we are creating. If nil, then we are creating
|
294
|
+
# a SoftwareTitle.
|
295
|
+
#
|
296
|
+
# @return [Integer] The id of the newly created object
|
297
|
+
#
|
298
|
+
####################
|
299
|
+
def create_on_server(cnx: Windoo.cnx)
|
300
|
+
unless @creating
|
301
|
+
raise Windoo::UnsupportedError,
|
302
|
+
"Do not call 'create_on_server' directly - use the .create class method."
|
303
|
+
end
|
304
|
+
|
305
|
+
@cnx = cnx
|
306
|
+
rsrc = creation_rsrc
|
307
|
+
resp = cnx.post rsrc, to_json
|
308
|
+
|
309
|
+
update_title_modify_time(resp)
|
310
|
+
|
311
|
+
# the container method woull only return nil for
|
312
|
+
# SoftwareTitle objects
|
313
|
+
container_id = container&.primary_id
|
314
|
+
|
315
|
+
new_id = handle_create_response(resp, container_id: container_id)
|
316
|
+
|
317
|
+
# no longer creating, future saves are updates
|
318
|
+
remove_instance_variable :@creating
|
319
|
+
|
320
|
+
new_id
|
321
|
+
end
|
322
|
+
|
323
|
+
# Update a single attribute on the server with the current value.
|
324
|
+
#
|
325
|
+
# @param attr_name [Symbol] The key from Class.json_attributes for the value
|
326
|
+
# we want to update
|
327
|
+
#
|
328
|
+
# @param alt_value [Object] A value to send that isn't the actual data for the attribute.
|
329
|
+
# If provided, the attr_name need not appear as a key in .json_attributes, but
|
330
|
+
# that name and this value will be sent to the API. See CriteriaManager#update_criterion
|
331
|
+
# for an example
|
332
|
+
#
|
333
|
+
#
|
334
|
+
# @return [Integer] the id of the updated item.
|
335
|
+
####################
|
336
|
+
def update_on_server(attr_name, new_value)
|
337
|
+
# This may be nil if given an alt name for an alt value
|
338
|
+
attr_def = self.class.json_attributes[attr_name]
|
339
|
+
|
340
|
+
if attr_def&.dig attr_name, :do_not_send
|
341
|
+
raise Windoo::UnsupportedError, "The value for #{attr_name} cannot be updated directly."
|
342
|
+
end
|
343
|
+
|
344
|
+
# convert the value, if needed, to API format
|
345
|
+
value_to_send =
|
346
|
+
if attr_def&.dig attr_name, :to_api
|
347
|
+
Windoo::Converters.send attr_def[:to_api], new_value.dup
|
348
|
+
else
|
349
|
+
new_value
|
350
|
+
end
|
351
|
+
|
352
|
+
json_to_put = { attr_name => value_to_send }.to_json
|
353
|
+
|
354
|
+
# should use our @cnx...
|
355
|
+
resp = cnx.put "#{self.class::RSRC_PATH}/#{primary_id}", json_to_put
|
356
|
+
update_title_modify_time(resp)
|
357
|
+
handle_update_response(resp)
|
358
|
+
end
|
359
|
+
|
360
|
+
# Remove the cnx object from
|
361
|
+
# the instance_variables used to create
|
362
|
+
# pretty-print (pp) output.
|
363
|
+
#
|
364
|
+
# @return [Array] the desired instance_variables
|
365
|
+
####################
|
366
|
+
def pretty_print_instance_variables
|
367
|
+
vars = instance_variables.sort
|
368
|
+
vars.delete :@cnx
|
369
|
+
vars.delete :@container
|
370
|
+
vars
|
371
|
+
end
|
372
|
+
|
373
|
+
# Private Instance Methods
|
374
|
+
####################
|
375
|
+
private
|
376
|
+
|
377
|
+
# update the timestamp on the title that contains this object
|
378
|
+
####################
|
379
|
+
def update_title_modify_time(resp)
|
380
|
+
if is_a? Windoo::SoftwareTitle
|
381
|
+
@lastModified = Time.parse(resp[:lastModified])
|
382
|
+
else
|
383
|
+
softwareTitle.update_modification_time
|
384
|
+
end
|
385
|
+
end
|
386
|
+
|
387
|
+
# figure out the resource path to use for POSTing this thing to the server
|
388
|
+
#
|
389
|
+
# @param container_id [Integer, nil] the id of the object that will
|
390
|
+
# contain the one we are creating. If nil, then we are creating
|
391
|
+
# a SoftwareTitle.
|
392
|
+
#
|
393
|
+
# @return [String] The resource path for POSTing to the server
|
394
|
+
#
|
395
|
+
####################
|
396
|
+
def creation_rsrc
|
397
|
+
# if no container id was given, the only thing we can create is
|
398
|
+
# a SoftwareTitle. Everything else is created via its container.
|
399
|
+
return Windoo::SoftwareTitle::RSRC_PATH unless @container
|
400
|
+
|
401
|
+
"#{self.class::CONTAINER_CLASS::RSRC_PATH}/#{@container.primary_id}/#{self.class::RSRC_PATH}"
|
402
|
+
end
|
403
|
+
|
404
|
+
end # module APICollection
|
405
|
+
|
406
|
+
end # module Mixins
|
407
|
+
|
408
|
+
end # module Windoo
|
@@ -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
|
+
# frozen_string_literal: true
|
7
|
+
|
8
|
+
module Windoo
|
9
|
+
|
10
|
+
# When using included modules to define constants,
|
11
|
+
# the constants have to be defined at the level where they will be
|
12
|
+
# referenced, or else they
|
13
|
+
# aren't available to other broken-out-and-included sub modules
|
14
|
+
#
|
15
|
+
# See https://cultivatehq.com/posts/ruby-constant-resolution/ for
|
16
|
+
# an explanation
|
17
|
+
|
18
|
+
# The minimum Ruby version needed for windoo
|
19
|
+
MINIMUM_RUBY_VERSION = '2.6.3'
|
20
|
+
|
21
|
+
# These are handy for testing values without making new arrays, strings, etc every time.
|
22
|
+
TRUE_FALSE = [true, false].freeze
|
23
|
+
|
24
|
+
# Empty strings are used in various places
|
25
|
+
BLANK = ''
|
26
|
+
|
27
|
+
module Mixins
|
28
|
+
|
29
|
+
# Constants useful throughout Windoo
|
30
|
+
# This should be included into the Jamf module
|
31
|
+
#####################################
|
32
|
+
module Constants
|
33
|
+
|
34
|
+
# when this module is included, also extend our Class Methods
|
35
|
+
def self.included(includer)
|
36
|
+
Windoo.load_msg "--> #{includer} is including Windoo::Constants"
|
37
|
+
end
|
38
|
+
|
39
|
+
end # module constants
|
40
|
+
|
41
|
+
end # module Mixins
|
42
|
+
|
43
|
+
end # module Windoo
|
@@ -0,0 +1,75 @@
|
|
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
|
+
module Windoo
|
11
|
+
|
12
|
+
module Mixins
|
13
|
+
|
14
|
+
# Module methods and aliases for dealing with the default connection
|
15
|
+
# This is extended into the API module
|
16
|
+
######################
|
17
|
+
module DefaultConnection
|
18
|
+
|
19
|
+
# When this module is extended into a class
|
20
|
+
def self.extended(extender)
|
21
|
+
Windoo.verbose_extend extender, self
|
22
|
+
end
|
23
|
+
|
24
|
+
# The current default Windoo::Connection instance.
|
25
|
+
#
|
26
|
+
# @return [Windoo::Connection]
|
27
|
+
#
|
28
|
+
def default_connection
|
29
|
+
@default_connection ||= Windoo::Connection.new name: :default
|
30
|
+
end
|
31
|
+
alias cnx default_connection
|
32
|
+
|
33
|
+
# Create a new Connection object and use it as the default for all
|
34
|
+
# future API calls. This will replace the existing default connection with
|
35
|
+
# a totally new one
|
36
|
+
#
|
37
|
+
# @param (See Windoo::Connection#initialize)
|
38
|
+
#
|
39
|
+
# @return [String] the to_s output of the new connection
|
40
|
+
#
|
41
|
+
def connect(url = nil, **params)
|
42
|
+
params[:name] ||= :default
|
43
|
+
@default_connection = Windoo::Connection.new url, **params
|
44
|
+
@default_connection.to_s
|
45
|
+
end
|
46
|
+
alias login connect
|
47
|
+
|
48
|
+
# Use the given Windoo::Connection object as the default connection, replacing
|
49
|
+
# the one that currently exists.
|
50
|
+
#
|
51
|
+
# @param connection [Windoo::Connection] The default Connection to use for future
|
52
|
+
# API calls
|
53
|
+
#
|
54
|
+
# @return [APIConnection] The connection now being used.
|
55
|
+
#
|
56
|
+
def cnx=(connection)
|
57
|
+
unless connection.is_a? Windoo::Connection
|
58
|
+
raise 'Title Editor connections must be instances of Windoo::Connection'
|
59
|
+
end
|
60
|
+
|
61
|
+
@default_connection = connection
|
62
|
+
end
|
63
|
+
|
64
|
+
# Disconnect the default connection
|
65
|
+
#
|
66
|
+
def disconnect
|
67
|
+
@default_connection.disconnect if @default_connection&.connected?
|
68
|
+
end
|
69
|
+
alias logout disconnect
|
70
|
+
|
71
|
+
end # module DefaultConnection
|
72
|
+
|
73
|
+
end # module Mixins
|
74
|
+
|
75
|
+
end # module Windoo
|
@@ -0,0 +1,34 @@
|
|
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 Windoo
|
10
|
+
|
11
|
+
module Mixins
|
12
|
+
|
13
|
+
# by default, instances of JSONObject subclasses are mutable
|
14
|
+
# as a whole, even if some of their attributes are not.
|
15
|
+
#
|
16
|
+
# To make them immutable, they should extend this module
|
17
|
+
# Windoo::Mixins::Immutable,
|
18
|
+
# which overrides the mutable? method
|
19
|
+
module Immutable
|
20
|
+
|
21
|
+
def self.extended(extender)
|
22
|
+
Windoo.verbose_extend extender, self
|
23
|
+
end
|
24
|
+
|
25
|
+
# this class is immutable
|
26
|
+
def mutable?
|
27
|
+
false
|
28
|
+
end
|
29
|
+
|
30
|
+
end # module Immutable
|
31
|
+
|
32
|
+
end # module Mixins
|
33
|
+
|
34
|
+
end # module Windoo
|
@@ -0,0 +1,38 @@
|
|
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 Windoo
|
10
|
+
|
11
|
+
module Mixins
|
12
|
+
|
13
|
+
module Loading
|
14
|
+
|
15
|
+
def self.extended(extender)
|
16
|
+
Windoo.verbose_extend extender, self
|
17
|
+
end
|
18
|
+
|
19
|
+
# Use the load_msg method defined for Zeitwerk
|
20
|
+
def load_msg(msg)
|
21
|
+
WindooZeitwerkConfig.load_msg msg
|
22
|
+
end
|
23
|
+
|
24
|
+
# Mention that a module is being included into something
|
25
|
+
def verbose_include(includer, includee)
|
26
|
+
load_msg "--> #{includer} is including #{includee}"
|
27
|
+
end
|
28
|
+
|
29
|
+
# Mention that a module is being extended into something
|
30
|
+
def verbose_extend(extender, extendee)
|
31
|
+
load_msg "--> #{extender} is extending #{extendee}"
|
32
|
+
end
|
33
|
+
|
34
|
+
end # module Loading
|
35
|
+
|
36
|
+
end # module Mixins
|
37
|
+
|
38
|
+
end # module Windoo
|
@@ -0,0 +1,102 @@
|
|
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 Windoo
|
10
|
+
|
11
|
+
module Mixins
|
12
|
+
|
13
|
+
module Patch
|
14
|
+
|
15
|
+
# An module that manages the Component in a
|
16
|
+
# Patch.
|
17
|
+
#
|
18
|
+
# Even though 'components' is plural, and
|
19
|
+
# they come from the server in an Array, at the moment there
|
20
|
+
# can only be one per Paatch.
|
21
|
+
#
|
22
|
+
# This module hides that confusion and allows you to work with
|
23
|
+
# just one
|
24
|
+
#
|
25
|
+
# If there's already an component, you can access it
|
26
|
+
# from the #component getter, and use that to directly
|
27
|
+
# update its values.
|
28
|
+
#
|
29
|
+
module Component
|
30
|
+
|
31
|
+
# Construcor
|
32
|
+
######################
|
33
|
+
def initialize(**init_data)
|
34
|
+
super
|
35
|
+
@component =
|
36
|
+
if @init_data[:components]&.first
|
37
|
+
Windoo::Component.instantiate_from_container(
|
38
|
+
container: self,
|
39
|
+
**@init_data[:components].first
|
40
|
+
)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# Public Instance Methods
|
45
|
+
####################################
|
46
|
+
|
47
|
+
# Add a component to this Patch. After its created,
|
48
|
+
# you can add criteria to it.
|
49
|
+
#
|
50
|
+
# NOTE: There can be only one per v. You will
|
51
|
+
# get an error if one already exists.
|
52
|
+
#
|
53
|
+
# @param name [String] The name of the component. Usually
|
54
|
+
# the same as the name of the Software Title it is
|
55
|
+
# associated with
|
56
|
+
#
|
57
|
+
# @param version [String] The version of the componen.
|
58
|
+
# Usually the same as the version of the Patch if it
|
59
|
+
# associated with
|
60
|
+
#
|
61
|
+
# @return [Integer] The id of the new Extension Attribute
|
62
|
+
#
|
63
|
+
def add_component(name:, version:)
|
64
|
+
if @component
|
65
|
+
raise Windoo::AlreadyExistsError,
|
66
|
+
'This Patch already has a Component. Either delete it before creating a new one, or update the existing one.'
|
67
|
+
end
|
68
|
+
|
69
|
+
@component = Windoo::Component.create(
|
70
|
+
container: self,
|
71
|
+
cnx: cnx,
|
72
|
+
name: name,
|
73
|
+
version: version
|
74
|
+
)
|
75
|
+
|
76
|
+
@component.componentId
|
77
|
+
end
|
78
|
+
|
79
|
+
# Delete the component from this Patch
|
80
|
+
#
|
81
|
+
# @return [Integer] The id of the deleted Extension Attribute
|
82
|
+
#
|
83
|
+
def delete_component
|
84
|
+
return unless @component
|
85
|
+
|
86
|
+
deleted_id = @component.delete
|
87
|
+
@component = nil
|
88
|
+
|
89
|
+
# patches without a component are not valid
|
90
|
+
# so must be disabled
|
91
|
+
container.disable
|
92
|
+
|
93
|
+
deleted_id
|
94
|
+
end
|
95
|
+
|
96
|
+
end # module ExtensionAttribute
|
97
|
+
|
98
|
+
end # module SoftwareTitle
|
99
|
+
|
100
|
+
end # module Mixins
|
101
|
+
|
102
|
+
end # module Windoo
|