Skip to content
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

Foreman: add options to support backwards compatibility with script #67070

Closed
wants to merge 2 commits into from

Conversation

jladdjr
Copy link
Contributor

@jladdjr jladdjr commented Feb 4, 2020

SUMMARY

Introduces two new options - legacy_groups and legacy_hostvars - to the foreman plugin. When both options are enabled, the plugin returns the same groups and hostvars returned by the foreman script.

Introducing this backwards compatibility in anticipation of awx adopting the foreman plugin (need a way to switch over to the plugin while still preserving the inventory structure that was present with the old script).

c.f. ansible/awx#3509

ISSUE TYPE
  • Feature Pull Request
COMPONENT NAME

foreman inventory plugin

ADDITIONAL INFORMATION

Overview of changes:

legacy_groups:

  • adds support for groups based on environment, location, organization hostvars
  • adds support for groups based on content_facet_attributes (i.e. lifecycle_environment and content_view)

legacy_hostvars:

  • by default, places hostvars under foreman key
  • moves foreman parameters under foreman_params key
  • existing behavior for foreman_facts already compatible with foreman script - left this unchanged

@ansibot
Copy link
Contributor

ansibot commented Feb 4, 2020

@ansibot ansibot added affects_2.10 This issue/PR affects Ansible v2.10 community_review In order to be merged, this PR must follow the community review workflow. feature This issue/PR relates to a feature request. foreman Foreman community inventory Inventory category needs_triage Needs a first human triage before being processed. support:community This issue/PR relates to code supported by the Ansible community. labels Feb 4, 2020
@ansibot
Copy link
Contributor

ansibot commented Feb 4, 2020

The test ansible-test sanity --test pylint [explain] failed with 1 error:

lib/ansible/plugins/inventory/foreman.py:221:4: dangerous-default-value: Dangerous default value [] as argument

The test ansible-test sanity --test pep8 [explain] failed with 3 errors:

lib/ansible/plugins/inventory/foreman.py:73:161: E501: line too long (170 > 160 characters)
lib/ansible/plugins/inventory/foreman.py:78:161: E501: line too long (197 > 160 characters)
lib/ansible/plugins/inventory/foreman.py:280:17: E303: too many blank lines (2)

click here for bot help

@ansibot ansibot added ci_verified Changes made in this PR are causing tests to fail. has_issue needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. and removed community_review In order to be merged, this PR must follow the community review workflow. labels Feb 4, 2020
@jladdjr jladdjr force-pushed the foreman_plugin_compatibility branch 2 times, most recently from aa22c3d to 8bdbbc8 Compare February 4, 2020 01:54
@ansibot ansibot added community_review In order to be merged, this PR must follow the community review workflow. and removed ci_verified Changes made in this PR are causing tests to fail. needs_revision This PR fails CI tests or a maintainer has requested a review/revision of the PR. labels Feb 4, 2020
Copy link
Member

@kdelee kdelee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shipit

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 4, 2020

@AlanCoding, @jainnikhil30 and I have been chatting about this PR. If I understand @AlanCoding and @jainnikhil30 correctly, it sounds like they are proposing that we use keyed_groups to get backwards compatibility with groups.

Here's my attempt at using keyed_groups to create the groups found in the script:
image

Groups returned by the script:
image

Groups returned by the plugin:
image

Comparing the two sets of groups:

  • foreman_environment_production looks great ✅
  • foreman_location_Default_Location’s name isn’t quite right b/c of capitalization and the added underscore ❌
  • foreman_organization__Default_Organization has these same issues ❌

As far as I can tell, keyed_groups gets us close, but not all the way there. Does anyone know of a way for us to get backwards compatibility with groups using keyed_groups (or anything else)?

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 4, 2020

Backwards compatibility with groups was one part of this PR, hostvars was the other part. As far as I can tell, there isn't a way to 'construct' the hostvars in a backwards compatible way without using custom logic like I've added here.

@bcoca
Copy link
Member

bcoca commented Feb 4, 2020

@jladdjr you can apply lower() to the key, jinja2 filter and python builtins are still available for you to get the same names. Also the extra underscore is the default separator, just use '' instead.

As for variables, look at the compose system, from a quick reading of the code you should be able to do the same, set the 'foreman' prefix and use the other options to get all the same parameters/variables.

@ansibot ansibot removed the needs_triage Needs a first human triage before being processed. label Feb 4, 2020
@ansibot ansibot added the stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. label Feb 12, 2020
@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 13, 2020

@bcoca - awesome, thanks for the tips, giving those a shot

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 14, 2020

@bcoca (cc @AlanCoding) took a look at the compose system (this is the related code, afaict) and the TLDR is that I'm not seeing a way to re-create what the script returns. Details below.


To go into a bit more detail about what kind of parity issues I'm seeing..

Script hostvars look like this:
image

plugin hostvars look like:
image

  • The script maps all hostvars to three keys: foreman, foreman_facts, and foreman_params (only foreman is shown in my screenshot).
  • The plugin doesn't file hostvars underneath any keys; all the hostvars are at the root level

Looking at the compose system, I'm not seeing a way to build the top-level dictionary I mentioned:

{
  "_meta": {
    "hostvars": {
      "myhost": {
        "foreman": {        <-- need to store hostvars under here
          <hostvars>
        },
        "foreman_facts": {  <-- .. and here
          <hostvars>
        },
        "foreman_params": { <-- .. and here
          <hostvars>
        },

If I try to use something like this in foreman.yml:

compose:
  foreman:
    architecture_id: foreman_architecture_id
    architecture_name: foreman_architecture_name

.. the compose system just creates a static dictionary mirroring what I have under compose. In order to build hostvars that form a dictionary, the compose system would need to do some recursion (which I don't see present right now).

Sorry for being a bit verbose - wanted to make sure I captured the scenario I'm trying to reproduce. Am I missing something here? Is compose able to fill out a dictionary of hostvars?

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 14, 2020

Meanwhile.. working on using keyed groups to get parity with group names.

Tried (1) setting separator field to empty string and (2) piping keys to lower. The group names still aren't quite lining up. Digging in now to see what's up.

example of changes I'm trying out:
image

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 15, 2020

Okay, I found a way to build the foreman groups using keyed_groups:

keyed_groups:
  - key: foreman_environment_name | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9\_]', '_') | regex_replace('none', '')
    prefix: foreman_environment_
    separator: ""
  - key: foreman_location_name | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9\_]', '_')
    prefix: foreman_location_
    separator: ""
  - key: foreman_organization_name | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9\_]', '_')
    prefix: foreman_organization_
    separator: ""
  - key: foreman_content_facet_attributes['lifecycle_environment_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9\_]', '_')
    prefix: foreman_lifecycle_environment_
    separator: ""
  - key: foreman_content_facet_attributes['content_view_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9\_]', '_')
    prefix: foreman_content_view
    separator: ""

So we can drop the changes here that build up groups. It still seems like the hostvar related changes are needed, though.

@ansibot ansibot removed the stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. label Feb 18, 2020
- Places hostvars in a dictionary with keys `foreman`, `foreman_facts`, and `foreman_params`
type: boolean
default: False
version_added: '2.10'
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe you could add the deprecated flag to this data?

Copy link
Contributor Author

@jladdjr jladdjr Feb 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You mean, we should basically say in advance something like, "in 2.13, we'll drop support for this (and officially break with the old script)" - is that what you mean?

@wenottingham - do we have a general policy about when awx can officially break ties with the old inv. scripts? Guess the answer to that may vary for each inventory source.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why would it be deprecated? is it that complex to maintain it as an option?

It's a breaking change regardless of when it happens.

Copy link
Contributor Author

@jladdjr jladdjr Feb 21, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@AlanCoding per @wenottingham's note, it seems like this option is something that we'll need to maintain for a while unless (1) there's some other way we plan on providing compatibility in the future (I can't think of any) or (2) we plan on actually transitioning the awx foreman plugin towards its vanilla behavior (but that would be a breaking change for awx users and I'm not sure we plan on ever doing that). In short, doesn't seem like we are planning on deprecating support for the new legacy_hostvars option.

@AlanCoding

This comment has been minimized.

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 18, 2020

@bcoca @ares @ehelms @ekohl @xprazak2 - this is ready for review again

@AlanCoding
Copy link
Member

This doesn't have the changes to get the legacy groups anymore, so that should make this simpler. +1 I absolutely advocate for merging this.

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 19, 2020

Even if the keyed_groups seem to work for now, it's hard to be sure it's really durable.

The jinja syntax (while a bit unwieldy) follows the old script's approach to creating groups pretty closely. I'm actually feeling pretty good about using keyed_groups (but if we did end up wanting to put some custom code in the plugin to handle this, I wouldn't be opposed to that either; they both effectively do the same thing).

Here's the final version of the plugin arguments that I came up with, btw:

plugin: foreman                                                                                                                                                                                                           user: my_user
password: my_pass
url: my_server
keyed_groups:                                                                                                                                                                                                               - key: foreman['environment_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9\_]', '_') | regex_replace('none', '')
    prefix: foreman_environment_                                                                                                                                                                                              separator: ""
  - key: foreman['location_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9\_]', '_')
    prefix: foreman_location_
    separator: ""
  - key: foreman['organization_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9\_]', '_')
    prefix: foreman_organization_
    separator: ""
  - key: foreman['content_facet_attributes']['lifecycle_environment_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9\_]', '_')
    prefix: foreman_lifecycle_environment_
    separator: ""
  - key: foreman['content_facet_attributes']['content_view_name'] | lower | regex_replace(' ', '') | regex_replace('[^A-Za-z0-9\_]', '_')
    prefix: foreman_content_view_
    separator: ""
legacy_hostvars: True
want_facts: True
want_params: True

When I pair the changes made to the plugin here, with these changes in awx -- which basically mirror the above plugin config snippet -- I confirmed that I'm able build the exact same inventory in awx when I run an inventory import with the script and plugin. Think we should ship it!

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 21, 2020

@ares @ehelms @ekohl @xprazak2 - do you all need anything in order to review this? Believe everything here is good-to-go.

@ares
Copy link
Contributor

ares commented Feb 24, 2020

@sjha4 thoughts?

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 27, 2020

What's needed in order to move this forward? The awx team is trying to get this in so that the foreman plugin can be adopted for Tower 3.7.

cc @ryanpetrello @blomquisg

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 27, 2020

ready_for_review

@ansibot ansibot added the stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. label Feb 27, 2020
@sjha4
Copy link
Contributor

sjha4 commented Feb 27, 2020

From the foreman inventory api perspective, this looks fine to me since all of the data massaging is happening post the inventory call to foreman and outside foreman. If the pre-change and post-change o/p are the same, the change looks good to me..

@sjha4
Copy link
Contributor

sjha4 commented Feb 27, 2020

From the foreman inventory api perspective, this looks fine to me since all of the data massaging is happening post the inventory call to foreman and outside foreman. If the pre-change and post-change o/p are the same, the change looks good to me..

Well..did not realize this was the plugin script and the larger change is to move awx to use this as the source..in which case the plugin script needs to use the foreman inventory report api like the https://github.com/ansible/ansible/blob/devel/contrib/inventory/foreman.py script does..

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 27, 2020

the plugin script needs to use the foreman inventory report api like the https://github.com/ansible/ansible/blob/devel/contrib/inventory/foreman.py script does..

@sjahl sounds like a good idea, but not a blocker for getting this in, right? Would vote for handling that separately.

The plugin currently breaks backwards compatibility w/out this change. We can move forward on other breaking changes / things needed for parity after getting this in. Making sure hostvars have parity is a pretty fundamental first step towards overall parity.

@sjha4
Copy link
Contributor

sjha4 commented Feb 27, 2020

@jladdjr : sounds good.. 👍

@jladdjr
Copy link
Contributor Author

jladdjr commented Feb 27, 2020

sweet, in that case.. motion made, seconded, ship_it?

@ares
Copy link
Contributor

ares commented Mar 2, 2020

shipit

@jladdjr
Copy link
Contributor Author

jladdjr commented Mar 6, 2020

superseded by theforeman/foreman-ansible-modules#591

@jladdjr jladdjr closed this Mar 6, 2020
@ansible ansible locked and limited conversation to collaborators Apr 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.10 This issue/PR affects Ansible v2.10 community_review In order to be merged, this PR must follow the community review workflow. feature This issue/PR relates to a feature request. foreman Foreman community has_issue inventory Inventory category stale_ci This PR has been tested by CI more than one week ago. Close and re-open this PR to get it retested. support:community This issue/PR relates to code supported by the Ansible community.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

8 participants