module JamfZeitwerkConfig
Jamf’s Zeitwerk Config and processes
Constants
- EAGER_LOAD_FILE
touch this file to make zeitwek eager-load everything when the gem is required.
- VERBOSE_LOADING_ENV
Or, set this ENV var to also make zeitverk and mixins send text to stderr
- VERBOSE_LOADING_FILE
touch this file to make zeitwerk and mixins send text to stderr as things load or get mixed in
Public Class Methods
eager_load_for_testing()
click to toggle source
For testing the Zeitwrk Loader. Normally we want autoloading on demand, eager loading loads everything so we can see it
To make this happen touch the file defined in EAGER_LOAD_FILE
# File lib/jamf/zeitwerk_config.rb 218 def self.eager_load_for_testing 219 return unless EAGER_LOAD_FILE.file? 220 221 loader.eager_load(force: true) 222 warn :loaded 223 # rescue Zeitwerk::NameError => e 224 # warn e.message 225 end
load_msg(msg)
click to toggle source
rubocop: disable Style/StderrPuts
# File lib/jamf/zeitwerk_config.rb 52 def self.load_msg(msg) 53 $stderr.puts msg if verbose_loading? 54 end
loader()
click to toggle source
The loader object for Xolo
# File lib/jamf/zeitwerk_config.rb 58 def self.loader 59 @loader 60 end
setup_zeitwerk_loader(zloader)
click to toggle source
Configure the Zeitwerk loader, See github.com/fxn/zeitwerk
# File lib/jamf/zeitwerk_config.rb 63 def self.setup_zeitwerk_loader(zloader) 64 @loader = zloader 65 66 # Ignore this file (more ignores below) 67 loader.ignore __FILE__ 68 69 ##### Collaped Paths 70 71 # these paths all define classes & modules directly below 'Jamf' 72 # If we didn't collapse them, then e.g. 73 # /jamf/api/base_classes/classic/group.rb 74 # would be expected to define 75 # Jamf::Api::BaseClasses::Classic::Group 76 # rather than what we want: 77 # Jamf::Group 78 ################################################### 79 80 loader.collapse("#{__dir__}/api") 81 82 loader.collapse("#{__dir__}/api/classic") 83 loader.collapse("#{__dir__}/api/classic/api_objects") 84 loader.collapse("#{__dir__}/api/classic/base_classes") 85 86 loader.collapse("#{__dir__}/api/jamf_pro") 87 loader.collapse("#{__dir__}/api/jamf_pro/api_objects") 88 loader.collapse("#{__dir__}/api/jamf_pro/mixins") 89 loader.collapse("#{__dir__}/api/jamf_pro/base_classes") 90 loader.collapse("#{__dir__}/api/jamf_pro/other_classes") 91 92 ##### Inflected Paths 93 94 # filenames => Constants, which don't adhere to zeitwerk's parsing standards. 95 # 96 # Mostly because the a filename like 'oapi_object' would be 97 # loaded by zeitwerk expecting it to define 'OapiObject', but it really 98 # defines 'OAPIObject' 99 ############################################### 100 101 # Connections 102 loader.inflector.inflect 'classic_api' => 'ClassicAPI' 103 loader.inflector.inflect 'jamf_pro_api' => 'JamfProAPI' 104 loader.inflector.inflect 'jamf_pro_api_error' => 'JamfProAPIError' 105 106 # API objects, resources, and mixins 107 loader.inflector.inflect 'oapi_schemas' => 'OAPISchemas' 108 loader.inflector.inflect 'oapi_object' => 'OAPIObject' 109 loader.inflector.inflect 'oapi_validate' => 'OAPIValidate' 110 111 loader.inflector.inflect 'jpapi_resource' => 'JPAPIResource' 112 113 loader.inflector.inflect 'api_object' => 'APIObject' 114 loader.inflector.inflect 'api_role' => 'APIRole' 115 loader.inflector.inflect 'api_client' => 'APIClient' 116 loader.inflector.inflect 'api_integration' => 'APIIntegration' 117 loader.inflector.inflect 'xml_workaround' => 'XMLWorkaround' 118 loader.inflector.inflect 'json_object' => 'JSONObject' 119 loader.inflector.inflect 'vppable' => 'VPPable' 120 loader.inflector.inflect 'osx_configuration_profile' => 'OSXConfigurationProfile' 121 loader.inflector.inflect 'jp_extendable' => 'JPExtendable' 122 loader.inflector.inflect 'mdm' => 'MDM' 123 loader.inflector.inflect 'ibeacon' => 'IBeacon' 124 loader.inflector.inflect 'powerbroker_identity_services' => 'PowerBroker' 125 loader.inflector.inflect 'admitmac' => 'ADmitMac' 126 loader.inflector.inflect 'ip_address' => 'IPAddress' 127 loader.inflector.inflect 'netboot_server' => 'NetBootServer' 128 loader.inflector.inflect 'vpp_account' => 'VPPAccount' 129 loader.inflector.inflect 'removable_macaddr' => 'RemovableMacAddress' 130 loader.inflector.inflect 'md_prestage_name' => 'MobileDevicePrestageName' 131 loader.inflector.inflect 'md_prestage_names' => 'MobileDevicePrestageNames' 132 loader.inflector.inflect 'md_prestage_skip_setup_items' => 'MobileDevicePrestageSkipSetupItems' 133 loader.inflector.inflect 'macos_managed_updates' => 'MacOSManagedUpdates' 134 loader.inflector.inflect 'macos_redeploy_mgmt_framework' => 'MacOSRedeployMgmtFramework' 135 loader.inflector.inflect 'filevault' => 'FileVault' 136 137 # deprecations, separated so they load only when used. 138 # When its time to get rid of them, delete the files from the 139 # 'deprecations' directory, and the matching line here. 140 loader.inflector.inflect('deprecated_api_constant' => 'API') 141 loader.inflector.inflect('deprecated_config_constant' => 'CONFIG') 142 loader.inflector.inflect('deprecated_api_connection_class' => 'APIConnection') 143 144 ##### Ingored Paths 145 146 # These should be ignored, some will be required directly 147 ##################################### 148 149 loader.ignore "#{__dir__}/db_connection.rb" 150 loader.ignore "#{__dir__}/ruby_extensions.rb" 151 loader.ignore "#{__dir__}/ruby_extensions" 152 loader.ignore "#{__dir__}/exceptions.rb" 153 loader.ignore "#{__dir__}/deprecations" 154 loader.ignore "#{__dir__}/deprecations.rb" 155 156 lib_dir = Pathname.new(__dir__).parent.to_s 157 loader.ignore "#{lib_dir}/ruby-jss.rb" 158 loader.ignore "#{lib_dir}/jss.rb" 159 loader.ignore "#{lib_dir}/jss-api.rb" 160 161 # See the comments and manual 'require' at the top of 162 # lib/jamf/api/jamf_pro/api_objects/api_role.rb 163 # for why we ignore this file. 164 loader.ignore "#{lib_dir}/jamf/api/jamf_pro/oapi_schemas/api_role.rb" 165 166 ##### Callbacks 167 168 # callback for when a specific file/constant loads 169 # duplicate and uncomment this if desired to react to 170 # specific things loading 171 ##################################### 172 # loader.on_load('Jamf::SomeClass') do |klass, abspath| 173 # Jamf.load_msg "I just loaded #{klass} from #{abspath}" 174 # end 175 176 # callback for when anything loads 177 # - const_path is like "Jamf::SomeClass" or "Jamf::SomeClass::SOME_CONST_ARRY" 178 # - value is the value that constant contains after loading, 179 # e.g. the class Jamf::SomeClass for 'Jamf::SomeClass' or 180 # an Array for the constant "Jamf::SomeClass::SOME_CONST_ARRY" 181 # - abspath is the full path to the file where the constant was loaded from. 182 ##################################### 183 loader.on_load do |const_path, value, abspath| 184 load_msg "Zeitwerk just loaded #{value.class} '#{const_path}' from:\n #{abspath}" 185 186 # Parse OAPI_PROPERTIES into getters and setters for subclasses of 187 # OAPIObject in the JPAPI. 188 # 189 # The class we just loaded must have this method and constant 190 # and the method must not have run already for the class or any superclass. 191 # This prevents running parse_oapi_properties again in subclasses that 192 # don't need to do that 193 if value.respond_to?(:oapi_properties_parsed?) && \ 194 defined?(value::OAPI_PROPERTIES) && \ 195 !value.oapi_properties_parsed? 196 197 parsed = value.parse_oapi_properties 198 load_msg "Parsed OAPI_PROPERTIES for #{value}" if parsed 199 end 200 201 # Generate the identifier list methods (.all_*) for subclasses of APIObject 202 # in the Classic API 203 if value.is_a?(Class) && value.superclass == Jamf::APIObject 204 205 done = value.define_identifier_list_methods 206 load_msg "Defined identifier list methods for #{value}" if done 207 end 208 end 209 210 loader.setup 211 end
verbose_loading?()
click to toggle source
Only look at the filesystem once.
# File lib/jamf/zeitwerk_config.rb 43 def self.verbose_loading? 44 return @verbose_loading unless @verbose_loading.nil? 45 46 @verbose_loading = VERBOSE_LOADING_FILE.file? 47 @verbose_loading ||= ENV.include? VERBOSE_LOADING_ENV 48 @verbose_loading 49 end