class Jamf::PatchPolicy

A Patch Policy in the JSS

When making new Patch Polices :patch_title and :target_version must be provided as well as :name.

:patch_title is the name or id of a currently active patch title

:target_version is the string identfier of an available version of the title. The target version MUST have a package assigned to it.

See {Jamf::PatchTitle} and {Jamf::PatchSource.available_titles} for methods to acquire such info.

@see Jamf::APIObject

Constants

AUTO_INSTALL_GRACE_PERIOD_MESSAGE
DFT_DEADLINE
DFT_DISTRIBUTION

the default dist method - not in ssvc

DFT_ENABLED
DFT_GRACE_PERIOD

The valud of grace_period when not defined

DFT_GRACE_PERIOD_MESSAGE
DFT_GRACE_PERIOD_SUBJECT
NO_DEADLINE

the value of deadline when there is no deadline

RSRC_BASE
RSRC_BY_PATCH_TITLE
RSRC_BY_PATCH_TITLE_LIST_KEY

TODO: complain to jamf about this - should be the same as RSRC_LIST_KEY

RSRC_LIST_KEY
RSRC_OBJECT_KEY
SCOPE_TARGET_KEY
USE_XML_WORKAROUND

See {Jamf::XMLWorkaround}

Attributes

allow_downgrade[R]

Can this title be downgraded to this version? @param new_val [Boolean] @return [Boolean]

allow_downgrade?[R]

Can this title be downgraded to this version? @param new_val [Boolean] @return [Boolean]

deadline[R]

How many days is the install deadline? @param days [Integer, Symbol] :none, or a positive integer. Integers < 1

have the same meaning as :none

@return [Integer, Symnol] :none, or a positive integer

downgradable?[R]

Can this title be downgraded to this version? @param new_val [Boolean] @return [Boolean]

enabled[R]

@return [Boolean] is this patch policy enabled?

enabled?[R]

@return [Boolean] is this patch policy enabled?

grace_period[R]

@param new_period [Integer] Negative integers will be saved as 0

@return [Integer] How many minutes does the user have to quit the killapps?

grace_period_duration[R]

@param new_period [Integer] Negative integers will be saved as 0

@return [Integer] How many minutes does the user have to quit the killapps?

grace_period_message[R]

@param subj [String] the new message

@return [String] The message displayed asking the user to quit the killapps

within @grace_period minutes
grace_period_notification_center_subject[R]

@param subj [String] the new subject

@return [String] The Subject of the message displayed asking the user to

quit the killapps within @grace_period minutes
grace_period_subject[R]

@param subj [String] the new subject

@return [String] The Subject of the message displayed asking the user to

quit the killapps within @grace_period minutes
incremental_update[R]

@return [Boolean] must this patch be installed only over the prev. version?

incremental_update?[R]

@return [Boolean] must this patch be installed only over the prev. version?

kill_apps[R]

@return [Array<Hash>] The apps that cannot be running when this is installed.

each Hash contains :kill_app_name and :kill_app_bundle_id, both Strings
minimum_os[R]

@return [String] The min. OS version require to install this patch

patch_title_id[R]

@return [Integer] the id of the Jamf::PatchTitle for this policy.

Can be set with the patch_title: param of .make, but is read-only after
that.
patch_unknown[R]

Can this policy run when we don’t know the prev. version? @param new_val [Boolean] @return [Boolean]

patch_unknown?[R]

Can this policy run when we don’t know the prev. version? @param new_val [Boolean] @return [Boolean]

reboot[R]

@return [Boolean] does this patch require a reboot after installation?

reboot?[R]

@return [Boolean] does this patch require a reboot after installation?

reboot_required[R]

@return [Boolean] does this patch require a reboot after installation?

reboot_required?[R]

@return [Boolean] does this patch require a reboot after installation?

release_date[R]

@return [Time] when the target_version was released

software_title_configuration_id[R]

@return [Integer] the id of the Jamf::PatchTitle for this policy.

Can be set with the patch_title: param of .make, but is read-only after
that.
software_title_id[R]

@return [Integer] the id of the Jamf::PatchTitle for this policy.

Can be set with the patch_title: param of .make, but is read-only after
that.
target_version[R]

When setting, the version must exist in the policy’s PatchTitle, and have a package assigned to it.

@param new_tgt_vers the new version for this Patch Policy.

@return [String] The version deployed by this policy

version[R]

When setting, the version must exist in the policy’s PatchTitle, and have a package assigned to it.

@param new_tgt_vers the new version for this Patch Policy.

@return [String] The version deployed by this policy

Public Class Methods

all_for_title(title, api: nil, cnx: Jamf.cnx) click to toggle source

Fetch name and id of all PatchPolicies tied to a given PatchTitle

@param title the name or id of the PatchTitle for which

to retrieve a list of patch policies

@return [Array<Hash>] the :id and :name of each policy for the title

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
252 def self.all_for_title(title, api: nil, cnx: Jamf.cnx)
253   cnx = api if api
254 
255   title_id = Jamf::PatchTitle.valid_id title
256   raise Jamf::NoSuchItemError, "No PatchTitle matching '#{title}'" unless title_id
257 
258   cnx.c_get("#{RSRC_BY_PATCH_TITLE}#{title_id}")[RSRC_BY_PATCH_TITLE_LIST_KEY]
259 end
fetch(searchterm = nil, **args) click to toggle source

Override APIObject.fetch, since there’s no …/patchpolicies/name/… endpoint @see APIObject#fetch

Calls superclass method Jamf::APIObject::fetch
    # File lib/jamf/api/classic/api_objects/patch_policy.rb
264 def self.fetch(searchterm = nil, **args)
265   cnx = args[:cnx]
266   cnx ||= Jamf.cnx
267 
268   name_search = args.delete :name
269   if name_search
270     id = valid_id name_search, cnx: cnx
271     raise Jamf::NoSuchItemError, "No #{self::RSRC_OBJECT_KEY} found #{err_detail}" unless id
272 
273     args[:id] = id
274   end
275   super
276 end
new(**data) click to toggle source

When making new Patch Polices :patch_title is required and is a Jamf::PatchTitle or the name or id of one

If target_version: is provided, it must exist in the PatchTitle, and must have a package assigned to it.

Calls superclass method Jamf::APIObject::new
    # File lib/jamf/api/classic/api_objects/patch_policy.rb
368 def initialize(**data)
369   super
370 
371   # creation...
372   unless in_jss
373     @init_data[:general] ||= {}
374     @init_data[:software_title_configuration_id] = validate_patch_title @init_data[:patch_title]
375     # need this set here for the validations below
376     @patch_title_id = @init_data[:software_title_configuration_id]
377 
378     # were we given target_version in the make params?
379     validate_target_version @init_data[:target_version] if @init_data[:target_version]
380     @init_data[:general][:target_version] = @init_data[:target_version]
381 
382     # other defaults
383     @init_data[:general][:enabled] = false
384     @init_data[:general][:allow_downgrade] = false
385     @init_data[:general][:patch_unknown] = false
386     @init_data[:general][:distribution_method] = DFT_DISTRIBUTION
387   end
388 
389   @patch_title_id = @init_data[:software_title_configuration_id]
390 
391   gen = @init_data[:general]
392   @enabled = gen[:enabled]
393   @target_version = gen[:target_version]
394   @allow_downgrade = gen[:allow_downgrade]
395   @patch_unknown = gen[:patch_unknown]
396 
397   @init_data[:user_interaction] ||= {}
398 
399   deadlines = @init_data[:user_interaction][:deadlines]
400   deadlines ||= {}
401   deadlines[:deadline_period] = DFT_DEADLINE if deadlines[:deadline_period].to_s.empty?
402   @deadline = deadlines[:deadline_enabled] ? deadlines[:deadline_period] : NO_DEADLINE
403 
404   grace = @init_data[:user_interaction][:grace_period]
405   grace ||= {}
406 
407   @grace_period = grace[:grace_period_duration]
408   @grace_period = DFT_GRACE_PERIOD if @grace_period.to_s.empty?
409 
410   @grace_period_subject = grace[:notification_center_subject]
411   @grace_period_subject = DFT_GRACE_PERIOD_SUBJECT if @grace_period_subject.to_s.empty?
412 
413   @grace_period_message = grace[:message]
414   @grace_period_message = DFT_GRACE_PERIOD_MESSAGE if @grace_period_message.to_s.empty?
415 
416   # read-only values, they come from the version.
417   @release_date = JSS.epoch_to_time gen[:release_date]
418   @incremental_update = gen[:incremental_update]
419   @reboot = gen[:reboot]
420   @minimum_os = gen[:minimum_os]
421   @kill_apps = gen[:kill_apps]
422 end

Public Instance Methods

allow_downgrade=(new_val) click to toggle source

see attr_reader :allow_downgrade

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
477 def allow_downgrade=(new_val)
478   return if new_val == allow_downgrade
479 
480   @allow_downgrade = Jamf::Validate.boolean new_val
481   @need_to_update = true
482 end
create() click to toggle source

Create a new PatchPolicy in the JSS

@return [Integer] the id of the new policy

Calls superclass method Jamf::SelfServable#create
    # File lib/jamf/api/classic/api_objects/patch_policy.rb
539 def create
540   validate_for_saving
541   # TODO: prepare for more cases where the POST rsrc is
542   # different from the PUT/GET/DELETE.
543   orig_rsrc = @rest_rsrc
544   @rest_rsrc = "#{RSRC_BY_PATCH_TITLE}#{CGI.escape patch_title_id.to_s}"
545   super
546   @rest_rsrc = orig_rsrc
547   refetch_version_info
548   id
549 end
deadline=(days) click to toggle source

see attr_reader :deadline

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
495 def deadline=(days)
496   unless days == NO_DEADLINE
497     days = Jamf::Validate.integer(days)
498     days = NO_DEADLINE unless days.positive?
499   end
500   return if days == deadline
501 
502   @deadline = days
503   @need_to_update = true
504 end
disable() click to toggle source

disable this policy

@return [void]

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
468 def disable
469   return unless enabled
470 
471   @enabled = false
472   @need_to_update = true
473 end
enable() click to toggle source

enable this policy

@return [void]

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
457 def enable
458   return if enabled
459 
460   @enabled = true
461   @need_to_update = true
462 end
grace_period=(mins) click to toggle source

see attr_reader :grace_period

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
508 def grace_period=(mins)
509   mins = Jamf::Validate.integer(mins)
510   mins = 0 if mins.negative?
511   return if mins == grace_period
512 
513   @grace_period = mins
514   @need_to_update = true
515 end
grace_period_message=(msg) click to toggle source

see attr_reader :grace_period_message

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
528 def grace_period_message=(msg)
529   return if grace_period_message == msg
530 
531   @grace_period_message = msg
532   @need_to_update = true
533 end
grace_period_subject=(subj) click to toggle source

see attr_reader :grace_period_subject

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
519 def grace_period_subject=(subj)
520   return if grace_period_subject == subj.to_s
521 
522   @grace_period_subject = subj.to_s
523   @need_to_update = true
524 end
patch_title(refresh = false) click to toggle source

The Jamf::PatchTitle to for this PatchPolicy

@param refresh [Boolean] Should the Title be re-fetched from the API?

@return [Jamf::PatchTitle, nil]

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
430 def patch_title(refresh = false)
431   @patch_title = nil if refresh
432   @patch_title ||= Jamf::PatchTitle.fetch id: patch_title_id, cnx: @cnx
433 end
patch_title_name() click to toggle source

@return [String] the name of the PatchTitle for this patch policy

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
437 def patch_title_name
438   return @patch_title.name if @patch_title
439 
440   Jamf::PatchTitle.map_all_ids_to(:name)[software_title_configuration_id]
441 end
patch_unknown=(new_val) click to toggle source

see attr_reader :patch_unknown

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
486 def patch_unknown=(new_val)
487   return if new_val == patch_unknown
488 
489   @patch_unknown = Jamf::Validate.boolean new_val
490   @need_to_update = true
491 end
target_version=(new_tgt_vers) click to toggle source

See attr_reader :target_version

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
445 def target_version=(new_tgt_vers)
446   return if new_tgt_vers == target_version
447 
448   @target_version = validate_target_version new_tgt_vers
449   @need_to_update = true
450   @refetch_for_new_version = true
451 end
update() click to toggle source

Update an existing PatchPolicy with changes from ruby

@return [Integer] the id of the policy

Calls superclass method Jamf::Scopable#update
    # File lib/jamf/api/classic/api_objects/patch_policy.rb
555 def update
556   validate_for_saving
557   super
558   refetch_version_info if @refetch_for_new_version
559   @refetch_for_new_version = false
560   id
561 end

Private Instance Methods

refetch_version_info() click to toggle source

Update our local version data after the target_version is changed

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
612 def refetch_version_info
613   tmp = self.class.fetch id: id, cnx: @cnx
614   @release_date = tmp.release_date
615   @incremental_update = tmp.incremental_update
616   @reboot = tmp.reboot
617   @minimum_os = tmp.minimum_os
618   @kill_apps = tmp.kill_apps
619 end
rest_xml() click to toggle source
    # File lib/jamf/api/classic/api_objects/patch_policy.rb
621 def rest_xml
622   doc = REXML::Document.new Jamf::Connection::XML_HEADER
623   obj = doc.add_element RSRC_OBJECT_KEY.to_s
624 
625   general = obj.add_element 'general'
626   general.add_element('target_version').text = target_version
627   general.add_element('name').text = name
628   general.add_element('enabled').text = enabled?.to_s
629   general.add_element('allow_downgrade').text = allow_downgrade
630   general.add_element('patch_unknown').text = patch_unknown
631 
632   # always include the scope if we have no id yet - we could be
633   # a clone of an existing object
634   obj << scope.scope_xml if scope.should_update? || @id.nil?
635 
636   add_self_service_xml doc
637 
638   # self svc xml gave us the user_interaction section
639   user_int = obj.elements['user_interaction']
640 
641   dlines = user_int.add_element 'deadlines'
642   if deadline == NO_DEADLINE
643     dlines.add_element('deadline_enabled').text = 'false'
644   else
645     dlines.add_element('deadline_enabled').text = 'true'
646     dlines.add_element('deadline_period').text = deadline.to_s
647   end
648 
649   grace = user_int.add_element 'grace_period'
650   grace.add_element('grace_period_duration').text = grace_period.to_s
651   grace.add_element('notification_center_subject').text = grace_period_subject.to_s
652   grace.add_element('message').text = grace_period_message.to_s
653 
654   doc.to_s
655 end
validate_for_saving() click to toggle source
    # File lib/jamf/api/classic/api_objects/patch_policy.rb
606 def validate_for_saving
607   validate_target_version target_version
608 end
validate_patch_title(a_title) click to toggle source

raise an error if the patch title we’re trying to use isn’t available in the jss. If handed a PatchTitle instance, we assume it came from the JSS

@param new_title[String,Integer,Jamf::PatchTitle] the title to validate

@return [Integer] the id of the valid title

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
574 def validate_patch_title(a_title)
575   if a_title.is_a? Jamf::PatchTitle
576     @patch_title = a_title
577     return a_title.id
578   end
579   raise Jamf::MissingDataError, ':patch_title is required' unless a_title
580 
581   title_id = Jamf::PatchTitle.valid_id a_title, cnx: @cnx
582   return title_id if title_id
583 
584   raise Jamf::NoSuchItemError, "No Patch Title matches '#{a_title}'"
585 end
validate_target_version(tgt_vers) click to toggle source

raise an exception if a given target version is not valid for this policy Otherwise return it

    # File lib/jamf/api/classic/api_objects/patch_policy.rb
590 def validate_target_version(tgt_vers)
591   raise Jamf::MissingDataError, "target_version can't be nil" unless tgt_vers
592 
593   Jamf::Validate.non_empty_string tgt_vers
594 
595   unless patch_title(:refresh).versions.key? tgt_vers
596     errmsg = "Version '#{tgt_vers}' does not exist for title: #{patch_title_name}."
597     raise Jamf::NoSuchItemError, errmsg
598   end
599 
600   return tgt_vers if patch_title.versions_with_packages.key? tgt_vers
601 
602   errmsg = "Version '#{tgt_vers}' cannot be used in Patch Policies until a package is assigned to it."
603   raise Jamf::UnsupportedError, errmsg
604 end