Top Level Namespace

Defined Under Namespace

Modules: FileTest, Jamf, JamfRubyExtensions Classes: Array, Hash, IPAddr, Object, Pathname, String, Time

Constant Summary collapse

JAMF_VERBOSE_LOADING_FILE =

touch this file to make zeitwerk and mixins send text to stderr as things load or get mixed in

Pathname.new('/tmp/ruby-jss-verbose-loading')
JAMF_VERBOSE_LOADING_ENV =

Or, set this ENV var to also make zeitverk and mixins send text to stderr

'RUBY_JSS_VERBOSE_LOADING'.freeze
JAMF_ZEITWERK_EAGER_LOAD_FILE =

touch this file to make zeitwek eager-load everything when the gem is required.

Pathname.new('/tmp/ruby-jss-zeitwerk-eager-load')
JSS =

JSS module is now a synonym for Jamf module

Jamf

Instance Method Summary collapse

Instance Method Details

#eager_load_for_testingObject

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 JAMF_ZEITWERK_EAGER_LOAD_FILE in jamf.rb



155
156
157
158
159
160
161
162
# File 'lib/zeitwerk_config.rb', line 155

def eager_load_for_testing
  return unless JAMF_ZEITWERK_EAGER_LOAD_FILE.file?

  @loader.eager_load(force: true)
  warn :loaded
# rescue Zeitwerk::NameError => e
#   warn e.message
end

#setup_zeitwerk_loader(loader) ⇒ Object

Configure the Zeitwerk loader, See github.com/fxn/zeitwerk



25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
# File 'lib/zeitwerk_config.rb', line 25

def setup_zeitwerk_loader(loader)
  @loader = loader

  # Ignore this file (more ignores below)
  loader.ignore __FILE__

  # these paths all define classes & modules directly below 'Jamf'
  # If we didn't collaps them, then e.g.
  #   /jamf/api/base_classes/classic/group.rb
  # would be expected to define
  #   Jamf::Api::BaseClasses::Classic::Group
  # rather than what we want:
  #  Jamf::Group
  ###################################################

  loader.collapse("#{__dir__}/jamf/api")

  loader.collapse("#{__dir__}/jamf/api/classic")
  loader.collapse("#{__dir__}/jamf/api/classic/api_objects")
  loader.collapse("#{__dir__}/jamf/api/classic/base_classes")

  loader.collapse("#{__dir__}/jamf/api/jamf_pro")
  loader.collapse("#{__dir__}/jamf/api/jamf_pro/api_objects")
  loader.collapse("#{__dir__}/jamf/api/jamf_pro/mixins")
  loader.collapse("#{__dir__}/jamf/api/jamf_pro/base_classes")
  loader.collapse("#{__dir__}/jamf/api/jamf_pro/other_classes")

  loader.collapse("#{__dir__}/jamf/deprecations")

  # filenames => Constants, which don't adhere to zeitwerk's parsing standards
  # Mostly because the a filename like 'oapi_object' would be
  # loaded by zeitwerk expecting it to define 'OapiObject', but it really
  # defines 'OAPIObject'
  ###############################################

  # Connections
  loader.inflector.inflect 'classic_api' => 'ClassicAPI'
  loader.inflector.inflect 'jamf_pro_api' => 'JamfProAPI'
  loader.inflector.inflect 'jamf_pro_api_error' => 'JamfProAPIError'

  # API objects, resources, and mixins
  loader.inflector.inflect 'oapi_schemas' => 'OAPISchemas'
  loader.inflector.inflect 'oapi_object' => 'OAPIObject'
  loader.inflector.inflect 'oapi_validate' => 'OAPIValidate'

  loader.inflector.inflect 'jpapi_resource' => 'JPAPIResource'

  loader.inflector.inflect 'api_object' => 'APIObject'
  loader.inflector.inflect 'xml_workaround' => 'XMLWorkaround'
  loader.inflector.inflect 'json_object' => 'JSONObject'
  loader.inflector.inflect 'vppable' => 'VPPable'
  loader.inflector.inflect 'osx_configuration_profile' => 'OSXConfigurationProfile'
  loader.inflector.inflect 'jp_extendable' => 'JPExtendable'
  loader.inflector.inflect 'mdm' => 'MDM'
  loader.inflector.inflect 'ibeacon' => 'IBeacon'
  loader.inflector.inflect 'powerbroker_identity_services' => 'PowerBroker'
  loader.inflector.inflect 'admitmac' => 'ADmitMac'
  loader.inflector.inflect 'ip_address' => 'IPAddress'
  loader.inflector.inflect 'netboot_server' => 'NetBootServer'
  loader.inflector.inflect 'vpp_account' => 'VPPAccount'
  loader.inflector.inflect 'removable_macaddr' => 'RemovableMacAddress'
  loader.inflector.inflect 'md_prestage_name' => 'MobileDevicePrestageName'
  loader.inflector.inflect 'md_prestage_names' => 'MobileDevicePrestageNames'
  loader.inflector.inflect 'md_prestage_skip_setup_items' => 'MobileDevicePrestageSkipSetupItems'

  # deprecations, separated so they load only when used
  loader.inflector.inflect("deprecated_api_constant" => "API")
  loader.inflector.inflect("deprecated_config_constant" => "CONFIG")

  # These should be ignored, some will be required directly
  #####################################

  loader.ignore "#{__dir__}/jamf/api/jamf_pro/pre_oapi"

  loader.ignore "#{__dir__}/jamf/db_connection.rb"
  loader.ignore "#{__dir__}/jamf/ruby_extensions.rb"
  loader.ignore "#{__dir__}/jamf/ruby_extensions"
  loader.ignore "#{__dir__}/jamf/exceptions.rb"
  loader.ignore "#{__dir__}/jss-api.rb"
  loader.ignore "#{__dir__}/jss.rb"
  loader.ignore "#{__dir__}/ruby-jss.rb"

  # callback for when a specific file/constant loads
  #####################################
  loader.on_load('Jamf::SomeClass') do |klass, abspath|
    Jamf.load_msg "I just loaded #{klass} from #{abspath}"
  end

  # callback for when anything loads
  #  - const_path is like "Jamf::SomeClass" or "Jamf::SomeClass::SOME_CONST_ARRY"
  #  - value is the value that constant contains after loading,
  #    e.g. a the class Jamf::SomeClass for 'Jamf::SomeClass' or
  #    and Array for the constant  "Jamf::SomeClass::SOME_CONST_ARRY"
  #  - abspath is the full path to the file where the constant was loaded from.
  #####################################
  loader.on_load do |const_path, value, abspath|
    Jamf.load_msg "Zeitwerk just loaded #{value.class} '#{const_path}' from:\n  #{abspath}"

    # Parse OAPI_PROPERTIES into getters and setters for subclasses of
    # OAPIObject in the JPAPI.
    # The class we just loaded must have this method and constant
    # and the constant must be defined directly in the file we just loaded.
    # This prevents running parse_oapi_properties again in subclasses that
    # don't need to do that
    if value.respond_to?(:parse_oapi_properties) && \
       defined?(value::OAPI_PROPERTIES) && \
       abspath == value.const_source_location(:OAPI_PROPERTIES).first

      parsed = value.parse_oapi_properties
      Jamf.load_msg "Parsed OAPI_PROPERTIES for #{value}" if parsed
    end

    # Generate the identifier list methods (.all_*) for subclasses of APIObject
    # in the Classic API
    if value.is_a?(Class) && value.superclass == Jamf::APIObject

      done = value.define_identifier_list_methods
      Jamf.load_msg "Defined identifier list methods for #{value}" if done
    end
  end

  loader.setup
end