Class: Xolo::Server::Title
- Inherits:
-
Core::BaseClasses::Title
- Object
- Core::BaseClasses::Title
- Xolo::Server::Title
- Includes:
- Helpers::JamfPro, Helpers::Log, Helpers::Notification, Helpers::TitleEditor, Mixins::Changelog, Mixins::TitleJamfAccess, Mixins::TitleTedAccess
- Defined in:
- lib/xolo/server/title.rb
Overview
A Title in Xolo, as used on the server
The code in this file mostly deals with the data on the Xolo server itself, and general methods for manipulating the title.
Code for interacting with the Title Editor and Jamf Pro are in the helpers and mixins.
NOTE be sure to only instantiate these using the servers ‘instantiate_title’ method, or else they might not have all the correct innards
Constant Summary collapse
- TITLES_DIR =
On the server, xolo titles are represented by directories in this directory, named with the title name.
So a title ‘foobar’ would have a directory
(Xolo::Server::DATA_DIR)/titles/foobar/
and in there will be a file
.json
with the data for the Title instance itself
Also in there will be a ‘versions’ dir containing json files for each version of the title. See Version
Xolo::Server::DATA_DIR + 'titles'
- NEW_TITLE_CURRENT_VERSION =
when creating new titles in the title editor, This is the ‘currentVersion’, which is required when creating. When the first version/patch is added, the title’s value for this will be updated.
'0.0.0'
- VERSION_SCRIPT_FILENAME =
If a title has a ‘version_script’ the the contents are stored in the title dir in a file with this name
'version-script'
- UNINSTALL_SCRIPT_FILENAME =
If a title is uninstallable, it will have a script in Jamf, which is also saved in this file on the xolo server.
'uninstall-script'
- TITLE_EDITOR_EA_KEY_PREFIX =
In the TitleEditor, the version script is stored as an Extension Attribute - each title can only have one. and it needs a ‘key’, which is the name used to indicate the EA in various criteria, and is the EA name in Jamf Patch. The key is this value as a prefix on the title so for title ‘foobar’, it is ‘xolo-foobar’ That value is also used as the display name
Xolo::Server::JAMF_OBJECT_NAME_PFX
- JAMF_NORMAL_EA_NAME_SUFFIX =
The EA from the title editor, which is used in Jamf Patch cannot, unfortunately, be used as a criterion in normal smart groups or advanced searches. Since we need a smart group containing all macs with any version of the title installed, we need a second copy of the EA as a ‘normal’ EA.
(That group is used as an exclusion to any auto-install initial- install policies, so that those policies don’t stomp on the matching Patch Policies)
The ‘duplicate’ EA is named the same as the Titled Editor key (see TITLE_EDITOR_EA_KEY_PREFIX) with this suffix added. So for the Title Editor key ‘xolo-<title>’, we’ll also have a matching normal EA called ‘xolo-<title>-installed-version’
'-installed-version'
- JAMF_INSTALLED_GROUP_NAME_SUFFIX =
'-installed'
- JAMF_FROZEN_GROUP_NAME_SUFFIX =
'-frozen'
- JAMF_UNINSTALL_SUFFIX =
'-uninstall'
- JAMF_EXPIRE_SUFFIX =
'-expire'
- CLIENT_EXPIRE_COMMAND =
the expire policy will run this client command, appending the title We don’t specify a full path so that localized installations will work as long as its in roots default path e.g. /usr/local/bin vs /usr/local/pixar/bin
'xolo expire'
- SELF_SERVICE_ICON_FILENAME =
When we are given a Self Service icon for the title, we might not be ready to upload it to jamf, cuz until we have a version to pilot, there’s nothing IN jamf. So we always store it locally in this file inside the title dir. The extension from the original file will be appended, e.g. ‘.png’
'self-service-icon'
- JPAPI_PATCH_TITLE_RSRC =
The JPAPI endpoint for Patch Titles.
ruby-jss still uses the Classic API for Patch Titles, and won’t by migrated to JPAPI until Jamf fully implements all aspects of patch management to JPAPI. As of this writing, that’s not the case. But, the JPAPI endpoint for Patch Title Reporting returns more detailed data than the Classic API, so we use it here, and will keep using it as we move forward.
This is the top-level endpoint for all patch titles, see JPAPI_PATCH_REPORT_RSRC for the reporting endpoint below it.
TODO: Remove this and update relevant methods when ruby-jss is updated to use JPAPI for Patch Titles..
'v2/patch-software-title-configurations'
- JPAPI_PATCH_REPORT_RSRC =
The JPAPI endpoint for patch reporting. The JPAPI_PATCH_TITLE_RSRC is appended with “/<id>/#JPAPI_PATCH_REPORT_RSRC” to get the URL for the patch report for a specific title.
TODO: Remove this and update relevant methods when ruby-jss is updated to use JPAPI for Patch Titles..
'patch-report'
- SELF_SERVICE_INSTALL_BTN_TEXT =
'Install'
Constants included from Mixins::Changelog
Mixins::Changelog::TITLE_CHANGELOG_FILENAME
Constants included from Helpers::Notification
Helpers::Notification::ALERT_TOOL_EMAIL_PREFIX, Helpers::Notification::DFT_EMAIL_FROM
Constants included from Helpers::JamfPro
Helpers::JamfPro::PATCH_REPORT_JPAPI_PAGE_SIZE, Helpers::JamfPro::PATCH_REPORT_UNKNOWN_VERSION
Instance Attribute Summary collapse
-
#changes_for_update ⇒ Hash
readonly
Also when applying updates, this will hold the changes being made: the differences between tne current attributes and the new_data_for_update We’ll figure this out at the start of the update and can use it later to 1) avoid doing things we don’t need to 2) log the changes in the change log at the very end.
-
#current_action ⇒ Symbol
The current action being taken on this title one of :creating, :updating, :deleting.
-
#jamf_expire_policy_name ⇒ String
readonly
If a title is expirable, it will have a policy in Jamf named ‘xolo-<title>-expire’ that will run the expiration process daily, at checkin or using a trigger of the same name.
-
#jamf_frozen_group_name ⇒ String
readonly
For each title there will be a static group containing macs that should not get any automatic installs or updates, They should be ‘frozen’ at whatever version was installed when they were added to the group.
-
#jamf_installed_group_name ⇒ String
readonly
For each title there will be a smart group containing all macs that have any version of the title installed.
-
#jamf_manual_install_released_policy_name ⇒ Object
readonly
The name of the policy that does initial manual or self-service installs of the currently-released version of this title.
-
#jamf_uninstall_policy_name ⇒ String
readonly
If a title is uninstallable, it will have a policy in Jamf named ‘xolo-<title>-uninstall’ that will run the script of the same name, using a trigger of the same name.
-
#jamf_uninstall_script_name ⇒ String
readonly
If a title is uninstallable, it will have a script in Jamf named ‘xolo-<title>-uninstall’.
-
#new_data_for_update ⇒ Hash
readonly
when applying updates, the new data from xadm is stored here so it can be accessed by update-methods and compared to the current instance values both for updating the title, and the versions.
-
#releasing_version ⇒ String
If current action is :releasing, this is the version being released.
-
#server_app_instance ⇒ Xolo::Server::App
The instance of Xolo::Server::App that instantiated this title object.
-
#ssvc_icon_id ⇒ Integer
The Jamf Pro ID for the self-service icon once it has been uploaded.
-
#ted_id_number ⇒ Integer
The Windoo::SoftwareTitle#softwareTitleId.
Class Method Summary collapse
-
.all_titles ⇒ Array<String>
A list of all known titles, just the basenames of all the title_dirs.
-
.in_ted?(title, cnx:) ⇒ Boolean
Does the given title exist in the Title Editor?.
-
.jamf_normal_ea_name(title) ⇒ String
The display name of a version script as a normal EA in Jamf, which can be used in Smart Groups and Adv Searches.
-
.load(title) ⇒ Xolo::Server::Title
Instantiate from the local JSON file containing the current values for the given title.
-
.locked?(title) ⇒ Boolean
Is a title locked for updates?.
-
.ssvc_icon_file(title) ⇒ Pathname
The the local file containing the self-service icon.
-
.ted_ea_key(title) ⇒ String
The key and display name of a version script stored in the title editor as the ExtAttr for a given title.
-
.title_data_file(title) ⇒ Pathname
The the local JSON file containing the current values for the given title.
-
.title_dir(title) ⇒ Pathname
The title dir for a given title on the server, which may or may not exist.
-
.title_dirs ⇒ Array<Pathname>
A list of all known title dirs.
-
.uninstall_script_file(title) ⇒ Pathname
The the local file containing the code of the version script.
-
.version_script_file(title) ⇒ Pathname
The the local file containing the code of the version script.
Instance Method Summary collapse
- #admin ⇒ String
-
#create ⇒ void
Save a new title, adding to the local filesystem, Jamf Pro, and the Title Editor as needed.
-
#creating? ⇒ Boolean
Are we creating this title?.
-
#delete ⇒ void
Delete the title and all of its version.
-
#delete_version_script_file ⇒ void
Delete the version script file.
-
#deleting? ⇒ Boolean
Are we deleting this title?.
-
#deprecate_or_skip_version(vobj) ⇒ void
Deprecate or skip a version.
-
#generate_uninstall_script(script_or_pkg_ids) ⇒ String, Array
The uninstall script, provided or generated from the given pkg ids.
-
#initialize(data_hash) ⇒ Title
constructor
NOTE: be sure to only instantiate these using the servers ‘instantiate_title’ method, or else they might not have all the correct innards.
-
#jamf_cnx(refresh: false) ⇒ Jamf::Connection
A single Jamf Pro API connection to use for the life of this instance.
-
#jamf_normal_ea_name ⇒ String
The display name of a version script as a normal EA in Jamf, which can be used in Smart Groups and Adv Searches.
-
#lock ⇒ Object
Lock this title for updates.
-
#locked? ⇒ Boolean
Is this title locked for updates?.
-
#patch_report_rsrc ⇒ String
The URL path for the patch report for this title.
-
#prepend_version(version) ⇒ void
prepend a new version to the version_order.
-
#progress(msg, log: :debug) ⇒ void
Append a message to the progress stream file, optionally sending it also to the log.
-
#release(version_to_release) ⇒ void
Release a version of this title.
-
#release_version(vobj, rollback:) ⇒ void
release a specific version.
-
#releasing? ⇒ Boolean
Are we releasing a version this title?.
-
#remove_version(version) ⇒ void
remove a version from the version_order.
-
#repair(repair_versions: false) ⇒ void
Repair this title, and optionally all of its versions.
-
#repairing? ⇒ Boolean
Are we repairing this title?.
-
#reset_version_to_pilot(vobj) ⇒ void
reset a version to pilot status, this happens when rolling back (releasing a version older than the current release).
-
#save_local_data ⇒ void
Save our current data out to our JSON data file This overwrites the existing data.
-
#save_ssvc_icon(tempfile, orig_filename) ⇒ void
Save the self_service_icon from the upload tmpfile to the file in the data dir.
-
#save_uninstall_script ⇒ void
Save our current uninstall script out to our local file.
-
#save_version_script ⇒ void
Save our current version script out to our local file, but only if we aren’t using app_name and app_bundle_id and only if it’s changed.
- #session ⇒ Hash
-
#ssvc_icon_file ⇒ Pathname
The the local file containing the self-service icon.
-
#ted_cnx ⇒ Windoo::Connection
A single Title Editor connection to use for the life of this instance.
-
#title_data_file ⇒ Pathname
The title data file for this title on the server.
-
#title_dir ⇒ Pathname
The title dir for this title on the server.
-
#to_h ⇒ Object
Add more server-specific data to our hash.
-
#uninstall_script_contents ⇒ String
The code of the uninstall_script , if any, considering the new data of any changes being made.
-
#uninstall_script_file ⇒ Pathname
The the local file containing the code of the uninstall script.
-
#uninstall_script_template ⇒ String
The template zsh script for uninstalling via pkgutil.
-
#uninstallable? ⇒ Boolean
are we uninstallable?.
-
#unlock ⇒ Object
Unlock this v for updates.
-
#update(new_data) ⇒ void
Update this title, updating to the local filesystem, Jamf Pro, and the Title Editor, and applying any changes to existing versions as needed.
-
#update_local_instance_values ⇒ void
Update our instance attributes with any new data before saving the changes back out to the file system.
-
#update_versions_for_release(version_to_release) ⇒ void
Update all versions when releasing one.
-
#updating? ⇒ Boolean
Are we updating this title?.
-
#validate_release(version_to_release) ⇒ void
are we OK releasing a given version?.
-
#version_object(version) ⇒ Xolo::Server::Version
instantiate a version if this title.
-
#version_objects(refresh: false) ⇒ Array<Xolo::Server::Version>
An array of all current version objects NOTE: This might not be wise if hundreds of versions, but automated cleanup should help with that.
-
#version_script_contents ⇒ String
The code of the version script, if any, considering the new data of any changes being made.
-
#version_script_file ⇒ Pathname
The the local file containing the code of the version script.
Methods included from Mixins::TitleTedAccess
#any_ted_changes?, #apply_requirement_changes, #create_and_enable_stub_patch_in_ted, #create_ted_ea, #create_ted_title_requirements, #create_title_in_ted, #delete_ted_ea, #delete_title_from_ted, #enable_ted_title, included, #repair_ted_title, #requirement_change, #set_app_requirement, #set_ea_requirement, #set_ted_patch_component_criteria_after_update, #set_ted_title_requirement, #ted_ea_key, #ted_title, #ted_title_url, #update_ted_ea, #update_title_in_ted
Methods included from Mixins::TitleJamfAccess
#accept_jamf_patch_ea, #accept_jamf_patch_ea_via_api, #activate_jamf_patch_title, #add_title_to_self_service, #auto_accept_patch_ea_in_thread, #configure_jamf_expire_policy, #configure_jamf_installed_group, #configure_jamf_manual_install_released_policy, #configure_jamf_normal_ea, #configure_jamf_uninstall_policy, #configure_jamf_uninstall_script, #configure_pol_for_self_service, #create_jamf_manual_install_released_policy, #create_title_in_jamf, #delete_jamf_expire_policy, #delete_jamf_frozen_group, #delete_jamf_installed_group, #delete_jamf_manual_install_released_policy, #delete_jamf_normal_ea, #delete_jamf_patch_title, #delete_jamf_uninstall_policy, #delete_jamf_uninstall_script, #delete_title_from_jamf, #freeze_computers, #freeze_or_thaw_computers, #frozen_computers, included, #jamf_active_ted_titles, #jamf_expire_policy, #jamf_expire_policy_exist?, #jamf_expire_policy_url, #jamf_frozen_group, #jamf_frozen_group_exist?, #jamf_frozen_group_url, #jamf_gui_url, #jamf_installed_group, #jamf_installed_group_criteria, #jamf_installed_group_exist?, #jamf_installed_group_url, #jamf_manual_install_released_policy, #jamf_manual_install_released_policy_exist?, #jamf_manual_install_released_policy_url, #jamf_normal_ea, #jamf_normal_ea_contents, #jamf_normal_ea_exist?, #jamf_normal_ea_url, #jamf_patch_ea_awaiting_acceptance?, #jamf_patch_ea_contents, #jamf_patch_ea_data, #jamf_patch_ea_matches_version_script?, #jamf_patch_ea_url, #jamf_patch_title, #jamf_patch_title_id, #jamf_patch_title_url, #jamf_ted_available_titles, #jamf_ted_patch_source, #jamf_ted_title_active?, #jamf_ted_title_available?, #jamf_uninstall_policy, #jamf_uninstall_policy_exist?, #jamf_uninstall_policy_url, #jamf_uninstall_script, #jamf_uninstall_script_exist?, #jamf_uninstall_script_url, #need_to_accept_jamf_patch_ea?, #need_to_delete_jamf_uninstall_script?, #need_to_update_description?, #need_to_update_expiration?, #need_to_update_jamf_installed_group?, #need_to_update_jamf_normal_ea?, #need_to_update_jamf_uninstall_script?, #patch_report, #repair_frozen_group, #repair_jamf_expire_policy, #repair_jamf_manual_install_released_policy, #repair_jamf_normal_ea, #repair_jamf_title_objects, #repair_jamf_uninstall_policy, #repair_jamf_uninstall_script, #thaw_computers, #update_description_in_jamf, #update_ssvc, #update_ssvc_category, #update_ssvc_icon, #update_title_in_jamf, #update_versions_for_title_changes_in_jamf
Methods included from Mixins::Changelog
#backup_changelog, backup_file_dir, #changelog, #changelog_backup_file, #changelog_file, #changelog_lock, changelog_locks, #delete_changelog, #hostname_from_ip, included, #log_change, #log_update_changes, #note_changes_for_update_and_log
Methods included from Helpers::Notification
#email_from, included, #send_alert, #send_email, #send_email_alert, #server_fqdn, #server_name
Methods included from Helpers::Log
included, #log_debug, #log_error, #log_fatal, #log_info, #log_unknown, #log_warn, #logger, #session_svr_obj_id
Methods included from Helpers::TitleEditor
Methods included from Helpers::JamfPro
extended, included, #jamf_gui_url, #jamf_xolo_category_id, #valid_forced_exclusion_group_name
Constructor Details
#initialize(data_hash) ⇒ Title
NOTE: be sure to only instantiate these using the servers ‘instantiate_title’ method, or else they might not have all the correct innards
376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 |
# File 'lib/xolo/server/title.rb', line 376 def initialize(data_hash) super @ted_id_number ||= data_hash[:ted_id_number] @jamf_patch_title_id ||= data_hash[:jamf_patch_title_id] @version_order ||= [] @new_data_for_update = {} @changes_for_update = {} @jamf_installed_group_name = "#{Xolo::Server::JAMF_OBJECT_NAME_PFX}#{data_hash[:title]}#{JAMF_INSTALLED_GROUP_NAME_SUFFIX}" @jamf_frozen_group_name = "#{Xolo::Server::JAMF_OBJECT_NAME_PFX}#{data_hash[:title]}#{JAMF_FROZEN_GROUP_NAME_SUFFIX}" @jamf_manual_install_released_policy_name = "#{Xolo::Server::JAMF_OBJECT_NAME_PFX}#{data_hash[:title]}-install" @jamf_uninstall_script_name = "#{Xolo::Server::JAMF_OBJECT_NAME_PFX}#{data_hash[:title]}#{JAMF_UNINSTALL_SUFFIX}" @jamf_uninstall_policy_name = "#{Xolo::Server::JAMF_OBJECT_NAME_PFX}#{data_hash[:title]}#{JAMF_UNINSTALL_SUFFIX}" @jamf_expire_policy_name = "#{Xolo::Server::JAMF_OBJECT_NAME_PFX}#{data_hash[:title]}#{JAMF_EXPIRE_SUFFIX}" end |
Instance Attribute Details
#changes_for_update ⇒ Hash (readonly)
Also when applying updates, this will hold the changes being made: the differences between tne current attributes and the new_data_for_update We’ll figure this out at the start of the update and can use it later to 1) avoid doing things we don’t need to 2) log the changes in the change log at the very end
This is a Hash with keys of the attribute names that have changed the values are Hashes with keys of :old and :new e.g. { release_groups: { old: [‘foo’], new: [‘bar’] } }
352 353 354 |
# File 'lib/xolo/server/title.rb', line 352 def changes_for_update @changes_for_update end |
#current_action ⇒ Symbol
Returns The current action being taken on this title one of :creating, :updating, :deleting.
360 361 362 |
# File 'lib/xolo/server/title.rb', line 360 def current_action @current_action end |
#jamf_expire_policy_name ⇒ String (readonly)
If a title is expirable, it will have a policy in Jamf named ‘xolo-<title>-expire’ that will run the expiration process daily, at checkin or using a trigger of the same name.
319 320 321 |
# File 'lib/xolo/server/title.rb', line 319 def jamf_expire_policy_name @jamf_expire_policy_name end |
#jamf_frozen_group_name ⇒ String (readonly)
For each title there will be a static group containing macs that should not get any automatic installs or updates, They should be ‘frozen’ at whatever version was installed when they were added to the group. It will be named ‘xolo-<title>-frozen’
It will be used as an exclusion for the installation policies and the patch policy for each version.
Membership is maintained using ‘xadm freeze <title> <computer> [<computer> …]` and `xadm thaw <title> <computer> [<computer> …]`
Use ‘xadm report <title> frozen` to see a list.
If computer groups are used with freeze/thaw, they are expanded and their members added/removed individually in the static group
Since there is one such group per title, it’s name is stored here
294 295 296 |
# File 'lib/xolo/server/title.rb', line 294 def jamf_frozen_group_name @jamf_frozen_group_name end |
#jamf_installed_group_name ⇒ String (readonly)
For each title there will be a smart group containing all macs that have any version of the title installed. The smart group will be named ‘xolo-<title>-installed’
It will be used as an exclusion for the initial auto-installation policy for each version since if the title is installed at all, any installation is not ‘initial’ but an update, and will be handled by the Patch Policy.
Since there is one such group per title, it’s name is stored here
273 274 275 |
# File 'lib/xolo/server/title.rb', line 273 def jamf_installed_group_name @jamf_installed_group_name end |
#jamf_manual_install_released_policy_name ⇒ Object (readonly)
The name of the policy that does initial manual or self-service installs of the currently-released version of this title. It will be named ‘xolo-<title>-install’
299 300 301 |
# File 'lib/xolo/server/title.rb', line 299 def jamf_manual_install_released_policy_name @jamf_manual_install_released_policy_name end |
#jamf_uninstall_policy_name ⇒ String (readonly)
If a title is uninstallable, it will have a policy in Jamf named ‘xolo-<title>-uninstall’ that will run the script of the same name, using a trigger of the same name.
312 313 314 |
# File 'lib/xolo/server/title.rb', line 312 def jamf_uninstall_policy_name @jamf_uninstall_policy_name end |
#jamf_uninstall_script_name ⇒ String (readonly)
If a title is uninstallable, it will have a script in Jamf named ‘xolo-<title>-uninstall’
305 306 307 |
# File 'lib/xolo/server/title.rb', line 305 def jamf_uninstall_script_name @jamf_uninstall_script_name end |
#new_data_for_update ⇒ Hash (readonly)
when applying updates, the new data from xadm is stored here so it can be accessed by update-methods and compared to the current instance values both for updating the title, and the versions
337 338 339 |
# File 'lib/xolo/server/title.rb', line 337 def new_data_for_update @new_data_for_update end |
#releasing_version ⇒ String
Returns If current action is :releasing, this is the version being released.
364 365 366 |
# File 'lib/xolo/server/title.rb', line 364 def releasing_version @releasing_version end |
#server_app_instance ⇒ Xolo::Server::App
The instance of Xolo::Server::App that instantiated this title object. This is how we access things that are available in routes and helpers, like the single Jamf and TEd connections for this App instance.
326 327 328 |
# File 'lib/xolo/server/title.rb', line 326 def server_app_instance @server_app_instance end |
#ssvc_icon_id ⇒ Integer
Returns The Jamf Pro ID for the self-service icon once it has been uploaded.
356 357 358 |
# File 'lib/xolo/server/title.rb', line 356 def ssvc_icon_id @ssvc_icon_id end |
#ted_id_number ⇒ Integer
Returns The Windoo::SoftwareTitle#softwareTitleId.
329 330 331 |
# File 'lib/xolo/server/title.rb', line 329 def ted_id_number @ted_id_number end |
Class Method Details
.all_titles ⇒ Array<String>
Returns A list of all known titles, just the basenames of all the title_dirs.
163 164 165 |
# File 'lib/xolo/server/title.rb', line 163 def self.all_titles title_dirs.map(&:basename).map(&:to_s) end |
.in_ted?(title, cnx:) ⇒ Boolean
Returns Does the given title exist in the Title Editor?.
246 247 248 |
# File 'lib/xolo/server/title.rb', line 246 def self.in_ted?(title, cnx:) Windoo::SoftwareTitle.all_ids(cnx: cnx).include? title end |
.jamf_normal_ea_name(title) ⇒ String
Returns The display name of a version script as a normal EA in Jamf, which can be used in Smart Groups and Adv Searches.
177 178 179 |
# File 'lib/xolo/server/title.rb', line 177 def self.jamf_normal_ea_name(title) "#{ted_ea_key(title)}#{JAMF_NORMAL_EA_NAME_SUFFIX}" end |
.load(title) ⇒ Xolo::Server::Title
Instantiate from the local JSON file containing the current values for the given title
NOTE: All instantiation should happen using the #instantiate_title method in the server app instance. Please don’t call this method directly
237 238 239 240 |
# File 'lib/xolo/server/title.rb', line 237 def self.load(title) Xolo::Server.logger.debug "Loading title '#{title}' from file" new parse_json(title_data_file(title).read) end |
.locked?(title) ⇒ Boolean
Is a title locked for updates?
252 253 254 255 |
# File 'lib/xolo/server/title.rb', line 252 def self.locked?(title) curr_lock = Xolo::Server.object_locks.dig title, :expires curr_lock && curr_lock > Time.now end |
.ssvc_icon_file(title) ⇒ Pathname
Returns The the local file containing the self-service icon.
223 224 225 |
# File 'lib/xolo/server/title.rb', line 223 def self.ssvc_icon_file(title) title_dir(title).children.select { |c| c.basename.to_s.start_with? SELF_SERVICE_ICON_FILENAME }.first end |
.ted_ea_key(title) ⇒ String
Returns The key and display name of a version script stored in the title editor as the ExtAttr for a given title.
170 171 172 |
# File 'lib/xolo/server/title.rb', line 170 def self.ted_ea_key(title) "#{TITLE_EDITOR_EA_KEY_PREFIX}#{title}" end |
.title_data_file(title) ⇒ Pathname
The the local JSON file containing the current values for the given title
199 200 201 |
# File 'lib/xolo/server/title.rb', line 199 def self.title_data_file(title) title_dir(title) + "#{title}.json" end |
.title_dir(title) ⇒ Pathname
The title dir for a given title on the server, which may or may not exist.
188 189 190 |
# File 'lib/xolo/server/title.rb', line 188 def self.title_dir(title) TITLES_DIR + title end |
.title_dirs ⇒ Array<Pathname>
Returns A list of all known title dirs.
156 157 158 |
# File 'lib/xolo/server/title.rb', line 156 def self.title_dirs TITLES_DIR.children end |
.uninstall_script_file(title) ⇒ Pathname
Returns The the local file containing the code of the version script.
215 216 217 |
# File 'lib/xolo/server/title.rb', line 215 def self.uninstall_script_file(title) title_dir(title) + UNINSTALL_SCRIPT_FILENAME end |
.version_script_file(title) ⇒ Pathname
Returns The the local file containing the code of the version script.
207 208 209 |
# File 'lib/xolo/server/title.rb', line 207 def self.version_script_file(title) title_dir(title) + VERSION_SCRIPT_FILENAME end |
Instance Method Details
#admin ⇒ String
407 408 409 |
# File 'lib/xolo/server/title.rb', line 407 def admin session[:admin] end |
#create ⇒ void
This method returns an undefined value.
Save a new title, adding to the local filesystem, Jamf Pro, and the Title Editor as needed
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 |
# File 'lib/xolo/server/title.rb', line 664 def create lock @current_action = :creating self.creation_date = Time.now self.created_by = admin log_debug "creation_date: #{creation_date}, created_by: #{created_by}" # this will create the title as needed in the Title Editor create_title_in_ted create_title_in_jamf # save to file last, because saving to TitleEd and Jamf will # add some data progress 'Saving title data to Xolo server' save_local_data log_change msg: 'Title Created' # ssvc icon is uploaded in a separate process, and the # title data file will be updated as needed then. ensure unlock end |
#creating? ⇒ Boolean
Returns Are we creating this title?.
413 414 415 |
# File 'lib/xolo/server/title.rb', line 413 def creating? current_action == :creating end |
#delete ⇒ void
This method returns an undefined value.
Delete the title and all of its version
900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 |
# File 'lib/xolo/server/title.rb', line 900 def delete lock @current_action = :deleting progress "Deleting all versions of #{title}...", log: :debug # Delete them in reverse order (oldest first) so the jamf server doesn't # see each older version as being 'released' again as newer # ones are deleted. version_objects.reverse.each do |vers| # vers might be nil if it was already deleted # e.g. a prev. attempt to delete the title failed partway through vers&.delete update_title: false end delete_title_from_ted delete_title_from_jamf delete_changelog progress "Deleting Xolo server data for title '#{title}'", log: :info title_dir.rmtree ensure unlock end |
#delete_version_script_file ⇒ void
This method returns an undefined value.
Delete the version script file
889 890 891 892 893 894 895 |
# File 'lib/xolo/server/title.rb', line 889 def delete_version_script_file return unless version_script_file.file? log_debug "Deleting version script file: #{version_script_file}" version_script_file.delete end |
#deleting? ⇒ Boolean
Returns Are we deleting this title?.
431 432 433 |
# File 'lib/xolo/server/title.rb', line 431 def deleting? current_action == :deleting end |
#deprecate_or_skip_version(vobj) ⇒ void
This method returns an undefined value.
Deprecate or skip a version
1020 1021 1022 1023 1024 1025 1026 1027 1028 |
# File 'lib/xolo/server/title.rb', line 1020 def deprecate_or_skip_version(vobj) # don't do anything if the status is already deprecated or skipped # but if its released, we need to deprecate it vobj.deprecate if vobj.status == Xolo::Server::Version::STATUS_RELEASED # and skip it if its in pilot vobj.skip if vobj.status == Xolo::Server::Version::STATUS_PILOT end |
#generate_uninstall_script(script_or_pkg_ids) ⇒ String, Array
Returns The uninstall script, provided or generated from the given pkg ids.
573 574 575 576 577 578 |
# File 'lib/xolo/server/title.rb', line 573 def generate_uninstall_script(script_or_pkg_ids) # Its already a script, validated by xadm to start with #! return script_or_pkg_ids if script_or_pkg_ids.is_a? String uninstall_script_template.sub 'PKG_IDS_FROM_XOLO_GO_HERE', script_or_pkg_ids.join(' ') end |
#jamf_cnx(refresh: false) ⇒ Jamf::Connection
Returns a single Jamf Pro API connection to use for the life of this instance.
465 466 467 |
# File 'lib/xolo/server/title.rb', line 465 def jamf_cnx(refresh: false) server_app_instance.jamf_cnx refresh: refresh end |
#jamf_normal_ea_name ⇒ String
Returns The display name of a version script as a normal EA in Jamf, which can be used in Smart Groups and Adv Searches.
595 596 597 |
# File 'lib/xolo/server/title.rb', line 595 def jamf_normal_ea_name @jamf_normal_ea_name ||= self.class.jamf_normal_ea_name title end |
#lock ⇒ Object
Lock this title for updates
1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 |
# File 'lib/xolo/server/title.rb', line 1106 def lock raise Xolo::ServerError, 'Server is shutting down' if Xolo::Server.shutting_down? while locked? log_debug "Waiting for update lock on title '#{title}'..." if (Time.now.to_i % 5).zero? sleep 0.33 end Xolo::Server.object_locks[title] ||= { versions: {} } exp = Time.now + Xolo::Server::ObjectLocks::OBJECT_LOCK_LIMIT Xolo::Server.object_locks[title][:expires] = exp log_debug "Locked title '#{title}' for updates until #{exp}" end |
#locked? ⇒ Boolean
Is this title locked for updates?
1100 1101 1102 |
# File 'lib/xolo/server/title.rb', line 1100 def locked? self.class.locked?(title) end |
#patch_report_rsrc ⇒ String
Returns The URL path for the patch report for this title.
655 656 657 |
# File 'lib/xolo/server/title.rb', line 655 def patch_report_rsrc @patch_report_rsrc ||= "#{JPAPI_PATCH_TITLE_RSRC}/#{jamf_patch_title_id}/#{JPAPI_PATCH_REPORT_RSRC}" end |
#prepend_version(version) ⇒ void
This method returns an undefined value.
prepend a new version to the version_order
605 606 607 608 609 610 611 |
# File 'lib/xolo/server/title.rb', line 605 def prepend_version(version) lock version_order.unshift version save_local_data ensure unlock end |
#progress(msg, log: :debug) ⇒ void
This method returns an undefined value.
Append a message to the progress stream file, optionally sending it also to the log
451 452 453 |
# File 'lib/xolo/server/title.rb', line 451 def progress(msg, log: :debug) server_app_instance.progress msg, log: log end |
#release(version_to_release) ⇒ void
This method returns an undefined value.
Release a version of this title
932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 |
# File 'lib/xolo/server/title.rb', line 932 def release(version_to_release) lock @current_action = :releasing @releasing_version = version_to_release validate_release(version_to_release) progress "Releasing version #{version_to_release} of title '#{title}'", log: :info update_versions_for_release version_to_release # update the title self.released_version = version_to_release save_local_data ensure unlock end |
#release_version(vobj, rollback:) ⇒ void
This method returns an undefined value.
release a specific version
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 |
# File 'lib/xolo/server/title.rb', line 1003 def release_version(vobj, rollback:) vobj.release rollback: rollback # update the jamf_manual_install_released_policy to install this version msg = "Jamf: Setting policy #{jamf_manual_install_released_policy_name} to install the package for version '#{vobj.version}'" progress msg, log: :info pol = jamf_manual_install_released_policy pol.package_ids.each { |pid| pol.remove_package pid } pol.add_package vobj.jamf_pkg_id pol.save end |
#releasing? ⇒ Boolean
Returns Are we releasing a version this title?.
437 438 439 |
# File 'lib/xolo/server/title.rb', line 437 def releasing? current_action == :releasing end |
#remove_version(version) ⇒ void
This method returns an undefined value.
remove a version from the version_order
619 620 621 622 623 624 625 |
# File 'lib/xolo/server/title.rb', line 619 def remove_version(version) lock version_order.delete version save_local_data ensure unlock end |
#repair(repair_versions: false) ⇒ void
This method returns an undefined value.
Repair this title, and optionally all of its versions.
Look at the Title Editor title object, and ensure it’s correct based on the local data file.
- display name
- publisher
- EA or app-data
- ea name 'xolo-<title>'
- requirement criteria
- stub version if needed
- enabled
Then look at the various Jamf objects pertaining to this title, and ensure they are correct
- Accept Patch EA
- Normal EA 'xolo-<title>-installed-version'
- title-installed smart group 'xolo-<title>-installed'
- frozen static group 'xolo-<title>-frozen'
- manual/SSvc install-current-release policy 'xolo-<title>-install'
- trigger 'xolo-<title>-install'
- ssvc icon
- ssvc category
- description
- if uninstallable
- uninstall script 'xolo-<title>-uninstall'
- uninstall policy 'xolo-<title>-uninstall'
- if expirable
- expire policy 'xolo-<title>-expire'
- trigger 'xolo-<title>-expire'
1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 |
# File 'lib/xolo/server/title.rb', line 1079 def repair(repair_versions: false) lock @current_action = :repairing chg_log_msg = repair_versions ? 'Repairing title and all versions' : 'Repairing title only' log_change msg: chg_log_msg progress "Starting repair of title '#{title}'" repair_ted_title repair_jamf_title_objects return unless repair_versions version_objects.each do |vobj| progress '#########' vobj.repair end ensure unlock end |
#repairing? ⇒ Boolean
Returns Are we repairing this title?.
425 426 427 |
# File 'lib/xolo/server/title.rb', line 425 def repairing? current_action == :repairing end |
#reset_version_to_pilot(vobj) ⇒ void
This method returns an undefined value.
reset a version to pilot status, this happens when rolling back (releasing a version older than the current release)
1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 |
# File 'lib/xolo/server/title.rb', line 1035 def reset_version_to_pilot(vobj) # do nothing if its in pilot return if vobj.status == Xolo::Server::Version::STATUS_PILOT # this should be redundant with the above? return unless rollback # if we're here, we're rolling back to something older than this # version, and this version is currently released, deprecated or skipped. # We need to reset it to pilot. vobj.reset_to_pilot end |
#save_local_data ⇒ void
This method returns an undefined value.
Save our current data out to our JSON data file This overwrites the existing data.
778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 |
# File 'lib/xolo/server/title.rb', line 778 def save_local_data # create the dirs for the title title_dir.mkpath vdir = title_dir + Xolo::Server::Version::VERSIONS_DIRNAME vdir.mkpath save_version_script save_uninstall_script self.modification_date = Time.now self.modified_by = admin log_debug "Title '#{title}' noting modification by #{modified_by}" # do we have a stored self service icon? self.self_service_icon = ssvc_icon_file ? Xolo::ITEM_UPLOADED : nil log_debug "Saving local title data to: #{title_data_file}" title_data_file.pix_atomic_write to_json end |
#save_ssvc_icon(tempfile, orig_filename) ⇒ void
This method returns an undefined value.
Save the self_service_icon from the upload tmpfile to the file in the data dir.
This is run by the upload route, not the create or update methods here. xadm does the upload after creating or updating the title
860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 |
# File 'lib/xolo/server/title.rb', line 860 def save_ssvc_icon(tempfile, orig_filename) lock # here's where we'll store it on the server ext_for_file = orig_filename.split(Xolo::DOT).last new_basename = "#{SELF_SERVICE_ICON_FILENAME}.#{ext_for_file}" new_icon_file = title_dir + new_basename # delete any previous icon files existing_icon_file = ssvc_icon_file if existing_icon_file&.file? log_debug "Deleting older icon file: #{existing_icon_file.basename}" existing_icon_file.delete end log_debug "Saving self_service_icon '#{orig_filename}' to: #{new_basename}" tempfile.rename new_icon_file # the json file only stores 'uploaded' in the self_service_icon # attr. self.self_service_icon = Xolo::ITEM_UPLOADED save_local_data ensure unlock end |
#save_uninstall_script ⇒ void
This method returns an undefined value.
Save our current uninstall script out to our local file.
This won’t delete the script if it’s being removed, that happens elsewhere.
This overwrites the existing data.
829 830 831 832 833 834 835 836 837 838 839 |
# File 'lib/xolo/server/title.rb', line 829 def save_uninstall_script return if uninstall_script == Xolo::ITEM_UPLOADED || uninstall_ids == Xolo::ITEM_UPLOADED return if uninstall_script_contents.nil? log_debug "Saving uninstall script to: #{uninstall_script_file}" uninstall_script_file.pix_atomic_write uninstall_script_contents # the json file only stores 'uploaded' in uninstall_script # The actual script is saved in its own file. self.uninstall_script &&= Xolo::ITEM_UPLOADED end |
#save_version_script ⇒ void
This method returns an undefined value.
Save our current version script out to our local file, but only if we aren’t using app_name and app_bundle_id and only if it’s changed
This won’t delete the script if it’s being removed, that happens elsewhere.
This overwrites the existing data.
809 810 811 812 813 814 815 816 817 818 |
# File 'lib/xolo/server/title.rb', line 809 def save_version_script return if app_name || app_bundle_id return if version_script_contents.nil? log_debug "Saving version_script to: #{version_script_file}" version_script_file.pix_atomic_write version_script_contents # the json file only stores 'uploaded' in the version_script attr. self.version_script = Xolo::ITEM_UPLOADED end |
#session ⇒ Hash
400 401 402 403 |
# File 'lib/xolo/server/title.rb', line 400 def session server_app_instance&.session || {} # @session ||= {} end |
#ssvc_icon_file ⇒ Pathname
Returns The the local file containing the self-service icon.
485 486 487 |
# File 'lib/xolo/server/title.rb', line 485 def ssvc_icon_file @ssvc_icon_file ||= self.class.ssvc_icon_file title end |
#ted_cnx ⇒ Windoo::Connection
Returns a single Title Editor connection to use for the life of this instance.
458 459 460 |
# File 'lib/xolo/server/title.rb', line 458 def ted_cnx server_app_instance.ted_cnx end |
#title_data_file ⇒ Pathname
The title data file for this title on the server
479 480 481 |
# File 'lib/xolo/server/title.rb', line 479 def title_data_file @title_data_file ||= self.class.title_data_file title end |
#title_dir ⇒ Pathname
The title dir for this title on the server
472 473 474 |
# File 'lib/xolo/server/title.rb', line 472 def title_dir @title_dir ||= self.class.title_dir title end |
#to_h ⇒ Object
Add more server-specific data to our hash
1132 1133 1134 1135 1136 1137 |
# File 'lib/xolo/server/title.rb', line 1132 def to_h hash = super hash[:ted_id_number] = ted_id_number hash[:ssvc_icon_id] = ssvc_icon_id hash end |
#uninstall_script_contents ⇒ String
The code of the uninstall_script , if any, considering the new data of any changes being made
Returns nil if there is no uninstall_script, or if we are in the process of deleting it.
542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 |
# File 'lib/xolo/server/title.rb', line 542 def uninstall_script_contents return @uninstall_script_contents if defined? @uninstall_script_contents # use any new/incoming value if we have any # this might still be nil or an empty array if we are removing uninstallability curr_script = changes_for_update.dig(:uninstall_script, :new) || changes_for_update.dig(:uninstall_ids, :new) curr_script = nil if curr_script.pix_empty? # otherwise use the existing value curr_script ||= uninstall_script || uninstall_ids # now get the actual script @uninstall_script_contents = if curr_script.pix_empty? # removing uninstallability, or it was never added nil elsif curr_script == Xolo::ITEM_UPLOADED # nothing changed, use the one we have saved on disk uninstall_script_file.read else # this will be a new one from the changes_for_update generate_uninstall_script curr_script end # log_debug "Uninstall script contents: #{@uninstall_script_contents}" @uninstall_script_contents end |
#uninstall_script_file ⇒ Pathname
Returns The the local file containing the code of the uninstall script.
530 531 532 |
# File 'lib/xolo/server/title.rb', line 530 def uninstall_script_file @uninstall_script_file ||= self.class.uninstall_script_file title end |
#uninstall_script_template ⇒ String
Returns The template zsh script for uninstalling via pkgutil.
582 583 584 585 586 587 588 589 590 |
# File 'lib/xolo/server/title.rb', line 582 def uninstall_script_template # parent 1 = server # parent 2 = xolo # parent 3 = lib # parent 4 = xolo gem data_dir = Pathname.new(__FILE__).parent.parent.parent.parent + 'data' template_file = data_dir + 'uninstall-pkgs-by-id.zsh' template_file.read end |
#uninstallable? ⇒ Boolean
are we uninstallable?
845 846 847 |
# File 'lib/xolo/server/title.rb', line 845 def uninstallable? uninstall_script || !uninstall_ids.pix_empty? end |
#unlock ⇒ Object
Unlock this v for updates
1122 1123 1124 1125 1126 1127 1128 |
# File 'lib/xolo/server/title.rb', line 1122 def unlock curr_lock = Xolo::Server.object_locks.dig title, :expires return unless curr_lock Xolo::Server.object_locks[title].delete :expires log_debug "Unlocked title '#{title}' for updates" end |
#update(new_data) ⇒ void
This method returns an undefined value.
Update this title, updating to the local filesystem, Jamf Pro, and the Title Editor, and applying any changes to existing versions as needed.
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 |
# File 'lib/xolo/server/title.rb', line 697 def update(new_data) lock @current_action = :updating @new_data_for_update = new_data @changes_for_update = note_changes_for_update_and_log if @changes_for_update.pix_empty? progress 'No changes to make', log: :info return end log_info "Updating title '#{title}' for admin '#{admin}'" log_debug "Updating title with these changes: #{changes_for_update}" # changelog - log the changes now, and # if there is an error, we'll log that too # saying the above changes were not completed and to # look at the server log for details. log_update_changes # Do ted before doing things in Jamf update_title_in_ted update_title_in_jamf update_local_instance_values save_local_data # if we already have a version script, and it hasn't changed, the new data should # contain Xolo::ITEM_UPLOADED. If its nil, we shouldn't # have one at all and should remove the old one if its there delete_version_script_file unless new_data_for_update[:version_script] # Do This at the end - after all the versions/patches have been updated. # Jamf won't see the need for re-acceptance until after the title # (and at least one patch) have been re-enabled. accept_jamf_patch_ea if need_to_accept_jamf_patch_ea? # any new self svc icon will be uploaded in a separate process # and the local data will be updated again then # rescue => e log_change msg: "ERROR: The update failed and the changes didn't all go through!\n#{e.class}: #{e.}\nSee server log for details." # re-raise for proper error handling in the server app raise ensure unlock end |
#update_local_instance_values ⇒ void
This method returns an undefined value.
Update our instance attributes with any new data before saving the changes back out to the file system
750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 |
# File 'lib/xolo/server/title.rb', line 750 def update_local_instance_values # update instance data with new data before writing out to the filesystem. # Do this last so that the instance values can be compared to # new_data_for_update in the steps above. # Also, those steps might have updated some server-specific attributes # which will be saved to the file system as well. ATTRIBUTES.each do |attr, deets| # make sure these are updated elsewhere if needed, # e.g. modification data. next if deets[:read_only] next unless deets[:cli] new_val = new_data_for_update[attr] old_val = send(attr) next if new_val == old_val log_debug "Updating Xolo Title attribute '#{attr}': '#{old_val}' -> '#{new_val}'" send "#{attr}=", new_val end # update any other server-specific attributes here... end |
#update_versions_for_release(version_to_release) ⇒ void
This method returns an undefined value.
Update all versions when releasing one
969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 |
# File 'lib/xolo/server/title.rb', line 969 def update_versions_for_release(version_to_release) # get the Version objects and figure out our starting point, but process # them in reverse order so that we don't have two released versions at once all_versions = version_objects.reverse vobj_to_release = all_versions.find { |v| v.version == version_to_release } vobj_current_release = all_versions.find { |v| v.version == released_version } rollback = vobj_current_release && vobj_to_release < vobj_current_release progress "Rolling back from version #{released_version}", log: :info if rollback all_versions.each do |vobj| # This is the one we are releasing if vobj == vobj_to_release release_version(vobj, rollback: rollback) # This one is older than the one we're releasing # so its either deprecated or skipped elsif vobj < vobj_to_release deprecate_or_skip_version(vobj) # this one is newer than the one we're releasing # revert to pilot if appropriate else reset_version_to_pilot(vobj) end # if vobj == vobj_to_release end # all_versions.each end |
#updating? ⇒ Boolean
Returns Are we updating this title?.
419 420 421 |
# File 'lib/xolo/server/title.rb', line 419 def updating? current_action == :updating end |
#validate_release(version_to_release) ⇒ void
This method returns an undefined value.
are we OK releasing a given version?
953 954 955 956 957 958 959 960 961 962 963 |
# File 'lib/xolo/server/title.rb', line 953 def validate_release(version_to_release) if released_version == version_to_release raise Xolo::InvalidDataError, "Version '#{version_to_release}' of title '#{title}' is already released" end return if versions.include? version_to_release raise Xolo::NoSuchItemError, "No version '#{version_to_release}' for title '#{title}'" end |
#version_object(version) ⇒ Xolo::Server::Version
instantiate a version if this title
631 632 633 634 |
# File 'lib/xolo/server/title.rb', line 631 def version_object(version) log_debug "Instantiating version #{version} from Title instance #{title}" server_app_instance.instantiate_version(title: self, version: version) end |
#version_objects(refresh: false) ⇒ Array<Xolo::Server::Version>
Returns An array of all current version objects NOTE: This might not be wise if hundreds of versions, but automated cleanup should help with that.
640 641 642 643 644 645 646 647 648 649 650 651 |
# File 'lib/xolo/server/title.rb', line 640 def version_objects(refresh: false) @version_objects = nil if refresh return @version_objects if @version_objects @version_objects = version_order.map do |v| version_object v rescue Xolo::Core::Exceptions::NoSuchItemError next if deleting? raise end end |
#version_script_contents ⇒ String
The code of the version script, if any, considering the new data of any changes being made
Returns nil if there is no version script, or if we are in the process of deleting it.
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 |
# File 'lib/xolo/server/title.rb', line 503 def version_script_contents return @version_script_contents if defined? @version_script_contents curr_script = if changes_for_update&.key? :version_script # new, incoming script changes_for_update[:version_script][:new] else # the current attribute value, might be Xolo::ITEM_UPLOADED version_script end @version_script_contents = if curr_script.pix_empty? # no script, or deleting script nil elsif curr_script == Xolo::ITEM_UPLOADED # use the one we have saved on disk version_script_file.read else # this will be a new one from the changes_for_update curr_script end end |
#version_script_file ⇒ Pathname
Returns The the local file containing the code of the version script.
491 492 493 |
# File 'lib/xolo/server/title.rb', line 491 def version_script_file @version_script_file ||= self.class.version_script_file title end |