PixarAnimationStudios / ruby-jss

ruby-jss provides native ruby access to the REST APIs of Jamf Pro, an enterprise/education tool for managing Apple devices, from jamf.com. The Jamf module provides access to both APIs. Jamf Pro objects are implemented as classes and interact with each other. Authentication tokens, data format and other details are handled under the hood to allow simpler, intuitive automation of Jamf-related tasks.
http://pixaranimationstudios.github.io/jss-api-gem/index.html
Other
98 stars 28 forks source link

undefined class Jamf::OAPISchemas::MobileDeviceResponse #98

Closed j-o-lantern0422 closed 3 months ago

j-o-lantern0422 commented 4 months ago

Thank you for a great API client! We are using this gem in our rails project and when running tests with eager_load enabled in CI, we are encountering the following error.

Failure/Error: require_relative '../config/environment'

NameError:
  uninitialized constant Jamf::OAPISchemas::MobileDeviceResponse
# ./config/environment.rb:5:in `<top (required)>'
# ./spec/rails_helper.rb:4:in `require_relative'
# ./spec/rails_helper.rb:4:in `<top (required)>’

If enabled eager_load, all classes etc. are pre-loaded, so this gem's classes etc. are assumed to be loaded at that time. When I actually search the code of this gem, it looks like Jamf::OAPISchemas::MobileDeviceResponse is indeed not defined (this error no longer occurs when I define it in Rails application.rb).

Maybe there is a problem with my project, but I couldn't find Jamf::OAPISchemas::MobileDeviceResponse, at least as far as I searched, so I built an Issue.

j-o-lantern0422 commented 4 months ago

Probably an error occurs at this line when trying to load the relevant class.

https://github.com/PixarAnimationStudios/ruby-jss/blob/fffda1f88039c80cc3c4f8f741ac5939ed5a0471/lib/jamf/api/jamf_pro/oapi_schemas/mobile_device_inventory_search_results.rb#L79

glenfarclas17 commented 4 months ago

Hi and Thanks for creating this issue!

Since everything in Jamf::OAPISchemas is auto-generated from the OAPI3 definition of the Jamf Pro API, I suspect there's an error there somewhere. I'll see if I can find it and inform the folks at Jamf, or see if I an find why my code didn't generate it correctly.

I'll let you know what I find. Cheers, -Chris

PS: you can see the OAPI definition of the entire JP API at https://your.jamf.server/api/schema - this resource is also useful when looking at the definition (which is a very large JSON string) https://swagger.io/docs/specification/data-models/data-types/

glenfarclas17 commented 4 months ago

Looks like the bug is in my code that generates those classes automatically. Those classes are all part of the v2/mobile-devices/detail endpoint - which returns a MobileDeviceInventorySearchResults object, which in turn contains an array of MobileDeviceResponse objects. However MobileDeviceResponse isn't really a class, it's just a delegator of sorts - it resolves to either MobileDeviceTvOsInventory or MobileDeviceIosInventory depending on the kind machine being returned.

I think this is the only place in the JP API where this happens, but clearly my code that generates the ruby classes needs to handle it, so I'll see what I can do about that.

I would have totally hit this myself soon, since one of my current projects is to migrate ruby-jss's Jamf::MobileDevice class to be based on the JP API - it currently still uses the classic API for most everything.

Thanks again, and I'll let you know how it goes. Cheers, -Chris

nick-f commented 3 months ago

I started taking a look into this issue because this bit us today too.

I noticed an unhandled case when running bin/generate_object_models which https://github.com/PixarAnimationStudios/ruby-jss/pull/99 should handle better.

~Once #99 is merged, would regenerating the OAPI schemas help this issue any? I'm not sure if that's considered a breaking change for the gem or not.~ Edit: Nope. I just tried it with my fork of the gem and updated models built from Jamf 11.5.1, but still seeing the same error.

nick-f commented 3 months ago

@glenfarclas17 I might have a solution to this in #100 but I'd very much appreciate your close eyes on it as you understand the logic more deeply than I do. 🙏

It might not be a good solution so feel free to discard it entirely if that's the best thing to do. However I'm definitely not seeing the error that @j-o-lantern0422 reported (and I was seeing too) after re-generating the schema using the two fixes in #99 and #100.

The regenerated schema can be seen in this commit that isn't part of either of those PRs: https://github.com/nick-f/ruby-jss/commit/13a12c8c4c78b03ab7bf1100c55862f21b2fac82

glenfarclas17 commented 3 months ago

Heya Nick!

Sorry for the delay in responding. I just ran the generate_object_models with your changes, and I think it looks good! At least it generated the missing classes that @j-o-lantern0422 reported missing, and it looks like they might function correctly.

The missing mobile_device_response.rb class now exists and contains only

OAPI_PROPERTIES = {  }.merge(Jamf::OAPISchemas::MobileDeviceTvOsInventory::OAPI_PROPERTIES).merge(Jamf::OAPISchemas::MobileDeviceIosInventory::OAPI_PROPERTIES) # end OAPI_PROPERTIES

And while that merging might not be technically correct, it should work for now.

That is especially true now because since I discovered this issue with oneOf - which I described in my last comment above - I've been questioning the wisdom of using the auto-generated classes as I am, versus "hand building" them like I did with the Classic API objects. I know that Bryson, who maintains the Python SDK, is taking the hand-built approach, exactly because of issues like this, plus a large amount of inconsistency across endpoints in the JP API.

Now that I'm looking at implementing a very complex object (a "MobileDevice") via the JP API these things are becoming more apparent and daunting to build and maintain in the way I currently am.

I think I can still use the OAPI3 schema and even the auto-generated classes, but I suspect it'll be easier in the long run to NOT include them as an integral part of ruby-jss, but rather use them as scaffolding to build 'bespoke' classes, just a little less bespoke than those from the Classic API :-) I think the flexibility, and easier maintenance of the ruby-jss api as the JP API changes, will be worth it.

I'd love to hear your thoughts on the matter!

In the mean time - I'll pull in your changes to generate_object_models and the next time I push out a change, will include the new files that it generates, which should resolve this issue, #98

Cheers, and thanks for the contribution! -Chris

glenfarclas17 commented 3 months ago

I just pushed those changes as v 4.1.1b1

Could you give that a try gem install ruby-jss --pre should install it

Thanks!