-
Notifications
You must be signed in to change notification settings - Fork 163
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
port foreman_domain, foreman_search_facts and katello_content_credential to apypie #261
Conversation
@@ -87,36 +86,27 @@ | |||
RETURN = ''' # ''' | |||
|
|||
try: | |||
from ansible.module_utils.ansible_nailgun_cement import ( | |||
find_domain, | |||
find_locations, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This, orgs and proxies do make sense to me to keep since they often show up in APIs. Perhaps there needs to a compatible apypie helper?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about that (even had them at first), but then I thought that find_foo(…)
is not that shorter than find_resource_by_name('foo', …)
and having that for only a few resources is also weird?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There is still the thin=True
as well. Perhaps the normalization function should be factored out and do it there.
method: GET | ||
uri: https://foreman.example.com/katello/api/v2/ping | ||
uri: https://192.168.121.223/api/status |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I quite liked the foreman.example.com domain :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
blah :)
I'll fix the fixtures at some point, yeah.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Super awesome @evgeni I was wondering what happened with apypie only yesterday. really nice
|
||
|
||
def sanitize_entity_dict(entity_dict, name_map): | ||
return {value: entity_dict[key] for key, value in name_map.items() if key in entity_dict} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How about:
return {value: entity_dict[key] for key, value in name_map.items() if key in entity_dict} | |
result = {} | |
for (key, (value, normalization)) in name_map.items(): | |
if key in entity_dict: | |
if normalization: | |
result[value] = module.find_resources(normalization, entity_dict[key], thin=True) | |
else: | |
result[value]: entity_dict[key] | |
return result |
Though it doesn't deal with the by name/id problem, it does allow dropping a lot of code from individual modules. Perhaps the mapping needs to be a bit more expressive though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sanitize_entity_dict is something we also use in the nailgun based modules, so I'd prefer not to touch it just yet. but I agree, there is certainly room for further improvements
This now also includes an example for Katello 💃 |
module_utils/foreman_helper.py
Outdated
@@ -120,9 +124,13 @@ def find_resource(self, resource, search, failsafe=False, thin=False): | |||
result = self.show_resource(resource, result['id']) | |||
return result | |||
|
|||
def find_resource_by_name(self, resource, name, failsafe=False, thin=False): | |||
def find_resource_by_name(self, resource, name, organization_id=None, failsafe=False, thin=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We may want to allow passing in other params, for exmaple https://theforeman.org/plugins/katello/3.9/api/apidoc/v2/repository_sets/index.html requires product_id
, I'm fairly sure there are others.
But I think we can change this at a later date when/if we require them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yea, maybe this could be done with a dict parameter or with kwargs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, this is something I should change before merging!
Otherwise fixing the API later is pain.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
updated to be a dict.
Is this something that can be extended easily to be using APIv3 (Graphql)? |
I don't know much about the GraphQL API, but I don't think this will be easy. |
After looking a bit closer on how GraphQL works, this will not work with our GraphQL API as such, but we should be able to create a similar groundwork for APIv3 with learnings from this and previous PRs. |
I think this is now at a state where we should talk about: do we want that as a direction forward, or was this a nice PoC but we stick to Let me re-iterate the pros and cons for the switch: Pros
Cons
Known Bugs
|
Could we extend |
Rather than extending apipie's custom format, I'd rather invest in moving to the OpenAPI spec. apipie can already output that, but it's likely we need to enhance some things for better output. |
Is there any heuristic to check for an outdated apypie cache? |
@mdellweg yes. The cache is url based, so it will not clash. And apypie checks the last modified header too. |
Given all the emoji reactions to the initial PR comment, I'd think y'all are in favor of this, but can you express that a bit more explicitly please? :) |
I know we had the discussion about using nailgun. So the question that comes to my mind is: Will this be adopted as a successor of nailgun and also be used in robottelo? |
The way I see it, QE is, and operates like, a different team from the Katello/Foreman developers. There's a set of projects for using with Foreman in production (plugins, cli, ansible playbooks, etc.) which Foreman devs work on and a set of repositories used to test Satellite by QE (nailgun, robottelo, airgun, etc.) that QEs work on. This is the problem with Nailgun IMO - it's a QE utility, not a tested and vetted production-use Foreman API python library. The GitHub org which these utilities live is SatelliteQE - clearly not intended for upstream use. A secondary related issue with Nailgun is that it's "release cycle" (if you'd call it that) is tied to Satellite, not Foreman. We'd need buy in from QE to uproot the status quo and start tracking upstream releases, which happen 3X more frequently than downstream. If you didn't already guess, they are already very busy. Lastly, there's some packaging issue with Nailgun that has been previously mentioned due to one of its dependencies (python requests? idk). So, yes, 🚀 for a python library that is automatically built from apipie. When something changes upstream, there's no code to write or update, just an API doc to generate (and tests to re-run). |
Nailgun is, as I understand it, much more focused at verifying the API. This library is intended to just consume what's there. Perhaps Nailgun could even use apypie underneath, but that verification still needs to happen. |
Generally 👍 to this approach as it also feels like it will make cross-version usage more robust. How much work do you estimate it is to convert all entities? |
I actually think, entities can be migrated gradually. We can track this process in a new checklist issue. |
Ad @mdellweg's question: The packaging issue @akofink mentioned is not about Ad @ehelms question: As you can see from this PR, the diff for the actual module is quite small, but you'll need to run the tests against a live system a few times to get all the details right and I wouldn't be surprised if we find a few bugs while porting the first entities. Overall the amount of work is somehwere in the 30-60 minutes per entity, so not that much. And as @mdellweg wrote, this can (and should) happen gradually. (And I'd not convert all of them, just the ones covered by tests ;)) |
...which is the vast majority: (also i don't want to stop promoting this issue ;)) |
I think then my ask would be to snapshot the current pure nailgun either via establishing a version and thus release for the modules or simply branching the current state and then merging this with an eye towards a release milestone that is fully converted to apypie. |
I have one last concern before we can actively start to bring this forward: How would the fact module look like? I think it is the one that is fundamentally different and we should at least have something equivalent. |
@mdellweg that's a fair ask, I'll prep the facts module too, so you'll have an example :) |
@mdellweg there we go, I still need to re-record the VCR tapes, but it's working. please note, this "breaks" the api, as now we have to write |
|
||
|
||
def main(): | ||
|
||
module = ForemanAnsibleModule( | ||
module = ForemanApypieAnsibleModule( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this name going to stick, once we ridded nailgun?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As soon as we're back to one backend, we can switch the naming back. I don't mind either way.
I think i am ok with this. It is an adequate replacement. Thanks for taking that concern seriously. |
return_length: 0 | ||
- name: Run with invalid resource |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is currently not supported with apypie
and will need some love there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK for me.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For the sake of clarity, how will users know what resources are valid? I assume they won't today and we can address that once we have made the required changes in apypie?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct. My plan is to report back the available resources in the error message from apypie
when a non-available one is called, and then we can restore the code we had.
@ehelms I've created a |
I too am also fine with that, considering we are doing a new major release. With this PR, could you add something prominent to the README so users know about that branch? |
@sean797 done |
changed, _ = self.ensure_resource(resource, entity_dict, entity, state, check_missing, check_type, force_update) | ||
return changed | ||
|
||
def ensure_resource(self, resource, entity_dict, entity, state, check_missing=None, check_type=None, force_update=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I can only speculate, you didn't like the name naildown_entity
enough...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I just didn't want the problem to look like a nail ;)
a03fbcd
to
c7694dd
Compare
this should pass tests (again) and has a more or less clean history so will merge tomorrow when back in the office :) |
Some time ago, I've written apypie as a Python port of
apipie-bindings
. This has the benefit that it can fetch the API definition from the running Foreman instance and thus does not need to "know" about the various resources. It's far from feature complete (or even bug-free), but I thought it never will become if it has no users, so here we are.This PR ports
foreman_domain
toapypie
instead ofnailgun
. While doing so, I've tried to make theForemanAnsibleModule
API more Pythonic. The code also contains a fewFIXME
s, which I'm still unsure about how to handle cleanly. Also, the method/variable names are inconsistent, as I've copied a lot from thenailgun
helper, but only adapted the naming half way through.