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

hostgroup update with puppetclasses or description #1231

Closed
achevalet opened this issue May 20, 2021 · 8 comments
Closed

hostgroup update with puppetclasses or description #1231

achevalet opened this issue May 20, 2021 · 8 comments

Comments

@achevalet
Copy link
Contributor

SUMMARY

Hi, I've some issues with the hostgroup module:

  • it seems that puppetclasses cannot be updated
  • updating description when passing puppetclasses fails
  • puppetclass_ids is not returned at creation
ISSUE TYPE
  • Bug Report
ANSIBLE VERSION
ansible 2.10.6
  config file = None
  configured module search path = ['/home/neo/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python3.6/site-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 3.6.8 (default, Nov 16 2020, 16:55:22) [GCC 4.8.5 20150623 (Red Hat 4.8.5-44)]

COLLECTION VERSION
# /usr/local/lib/python3.6/site-packages/ansible_collections
Collection         Version
------------------ -------
theforeman.foreman 2.1.0  

KATELLO/FOREMAN VERSION
tfm-rubygem-katello-3.14.1-1.el7.noarch
foreman-1.24.3-1.el7.noarch

STEPS TO REPRODUCE
---
- hosts: localhost
  collections:
    - theforeman.foreman
  gather_facts: false
  tasks:
    - name: Ensure Hostgroup '{{ name }}' is {{ state }}
      hostgroup:
        name: "{{ name }}"
        updated_name: "{{ updated_name | default(omit) }}"
        parent: "{{ parent | default(omit) }}"
        description: "{{ description | default(omit) }}"
        locations: "{{ locations | default(omit) }}"
        organizations: "{{ organizations | default(omit) }}"
        compute_resource: "{{ compute_resource | default(omit) }}"
        compute_profile: "{{ compute_profile | default(omit) }}"
        domain: "{{ domain | default(omit) }}"
        subnet: "{{ subnet | default(omit) }}"
        subnet6: "{{ subnet6 | default(omit) }}"
        realm: "{{ realm | default(omit) }}"
        architecture: "{{ architecture | default(omit) }}"
        operatingsystem: "{{ operatingsystem | default(omit) }}"
        medium: "{{ installation_medium | default(omit) }}"
        ptable: "{{ ptable | default(omit) }}"
        pxe_loader: "{{ pxe_loader | default(omit) }}"
        root_pass: "{{ root_pass | default(omit) }}"
        environment: "{{ puppet_environment | default(omit) }}"
        puppetclasses: "{{ puppetclasses | default(omit) }}"
        config_groups: "{{ config_groups | default(omit) }}"
        puppet_proxy: "{{ puppet_proxy | default(omit) }}"
        puppet_ca_proxy: "{{ puppet_ca_proxy | default(omit) }}"
        openscap_proxy: "{{ openscap_proxy | default(omit) }}"
        organization: "{{ organization | default(omit) }}"
        content_source: "{{ content_source | default(omit) }}"
        lifecycle_environment: "{{ lifecycle_environment | default(omit) }}"
        content_view: "{{ content_view | default(omit) }}"
        parameters: "{{ parameters | default(omit) }}"
        state: "{{ state }}"
      register: result

    - debug:
        var: result.entity.hostgroups[0].puppetclass_ids
      when: state == "present"

    - name: Get hostgroup info
      when: state == "present"
      resource_info:
        resource: hostgroups
        info: true
        search: "title = {{ parent + '/' + name if parent is defined else name }}"
      register: result

    - debug:
        var: result.resources[0].puppetclasses
      when: state == "present"
EXPECTED RESULTS

puppetclasses and/or description updated on same run

ACTUAL RESULTS
$ ansible-playbook playbook.yaml -e name=test -e puppetclasses=docker -e state=present
...
    "result.entity.hostgroups[0].puppetclass_ids": "VARIABLE IS NOT DEFINED!"
...
    "result.resources[0].puppetclasses": [
        {
            "id": 170,
            "module_name": "docker",
            "name": "docker"
        }
    ]

$ ansible-playbook playbook.yaml -e name=test -e puppetclasses=docker,hosts -e state=present
...
    "result.entity.hostgroups[0].puppetclass_ids": [
        170
    ]
...
    "result.resources[0].puppetclasses": [
        {
            "id": 170,
            "module_name": "docker",
            "name": "docker"
        }
    ]

$ ansible-playbook playbook.yaml -e name=test -e puppetclasses=docker,hosts -e state=absent
$ ansible-playbook playbook.yaml -e name=test -e puppetclasses=docker,hosts -e state=present
...
    "result.entity.hostgroups[0].puppetclass_ids": "VARIABLE IS NOT DEFINED!"
...
    "result.resources[0].puppetclasses": [
        {
            "id": 170,
            "module_name": "docker",
            "name": "docker"
        },
        {
            "id": 282,
            "module_name": "hosts",
            "name": "hosts"
        }
    ]

$ ansible-playbook playbook.yaml -e name=test -e puppetclasses=docker,hosts -e description=test -e state=present
...
fatal: [localhost]: FAILED! => {"changed": false, "error": {"message": "Validation failed: Puppet class has already been taken"}, "msg": "Error while performing create on hostgroup_classes: 500 Server Error: Internal Server Error for url: https://katello-url/api/hostgroups/11263/puppetclass_ids"}

$ ansible-playbook playbook.yaml -e name=test -e description=test -e state=present
ok: [localhost]
...
    "result.entity.hostgroups[0].puppetclass_ids": [
        170,
        282
    ]
...
    "result.resources[0].puppetclasses": [
        {
            "id": 170,
            "module_name": "docker",
            "name": "docker"
        },
        {
            "id": 282,
            "module_name": "hosts",
            "name": "hosts"
        }
    ]

@achevalet
Copy link
Contributor Author

Note that we can update description in a separate task but it does not work for puppetclasses:

---
- hosts: localhost
  collections:
    - theforeman.foreman
  gather_facts: false
  tasks:
    - name: Ensure Hostgroup '{{ name }}' is {{ state }}
      hostgroup:
        name: "{{ name }}"
        updated_name: "{{ updated_name | default(omit) }}"
        parent: "{{ parent | default(omit) }}"
        # description: "{{ description | default(omit) }}"
        locations: "{{ locations | default(omit) }}"
        organizations: "{{ organizations | default(omit) }}"
        compute_resource: "{{ compute_resource | default(omit) }}"
        compute_profile: "{{ compute_profile | default(omit) }}"
        domain: "{{ domain | default(omit) }}"
        subnet: "{{ subnet | default(omit) }}"
        subnet6: "{{ subnet6 | default(omit) }}"
        realm: "{{ realm | default(omit) }}"
        architecture: "{{ architecture | default(omit) }}"
        operatingsystem: "{{ operatingsystem | default(omit) }}"
        medium: "{{ installation_medium | default(omit) }}"
        ptable: "{{ ptable | default(omit) }}"
        pxe_loader: "{{ pxe_loader | default(omit) }}"
        root_pass: "{{ root_pass | default(omit) }}"
        environment: "{{ puppet_environment | default(omit) }}"
        puppetclasses: "{{ puppetclasses | default(omit) }}"
        config_groups: "{{ config_groups | default(omit) }}"
        puppet_proxy: "{{ puppet_proxy | default(omit) }}"
        puppet_ca_proxy: "{{ puppet_ca_proxy | default(omit) }}"
        openscap_proxy: "{{ openscap_proxy | default(omit) }}"
        organization: "{{ organization | default(omit) }}"
        content_source: "{{ content_source | default(omit) }}"
        lifecycle_environment: "{{ lifecycle_environment | default(omit) }}"
        content_view: "{{ content_view | default(omit) }}"
        parameters: "{{ parameters | default(omit) }}"
        state: "{{ state }}"
      register: result

    - name: Update description on Hostgroup '{{ name }}'
      when: state == "present"
      hostgroup:
        name: "{{ name }}"
        parent: "{{ parent | default(omit) }}"
        description: "{{ description | default(omit) }}"
        state: "{{ state }}"

    - name: Update puppetclasses on Hostgroup '{{ name }}'
      when: state == "present"
      hostgroup:
        name: "{{ name }}"
        parent: "{{ parent | default(omit) }}"
        puppetclasses: "{{ puppetclasses | default(omit) }}"
        state: "{{ state }}"

    - name: Get hostgroup info
      when: state == "present"
      resource_info:
        resource: hostgroups
        info: true
        search: "title = {{ parent + '/' + name if parent is defined else name }}"
      register: result

    - name: Show hostgroup details
      when: state == "present"
      debug:
        var: result.resources[0] | dict2items | rejectattr("value", "equalto", none) | list | items2dict

@evgeni
Copy link
Member

evgeni commented May 25, 2021

@mdellweg please take a look if you have some spare cycles

@evgeni
Copy link
Member

evgeni commented May 27, 2021

One thing that I realized (and I think that's undocumented):

If you set description, the module uses that to find the OS, instead of the name field, which I think is wrong in retrospect

entity = None
# If we have a description, search for it
if 'description' in module_params and module_params['description'] != '':
search_string = 'description="{0}"'.format(module_params['description'])
entity = module.find_resource('operatingsystems', search_string, failsafe=True)
# If we did not yet find a unique OS, search by name & version
# In case of state == absent, those information might be missing, we assume that we did not find an operatingsytem to delete then
if entity is None and 'name' in module_params and 'major' in module_params:
search_string = ','.join('{0}="{1}"'.format(key, module_params[key]) for key in ('name', 'major', 'minor') if key in module_params)
entity = module.find_resource('operatingsystems', search_string, failsafe=True)

Wait, no, ignore me. The above is a valid bug, probably. But you're talking about HGs, not OSes.

mdellweg added a commit to mdellweg/foreman-ansible-modules that referenced this issue Jun 28, 2021
mdellweg added a commit to mdellweg/foreman-ansible-modules that referenced this issue Jun 28, 2021
mdellweg added a commit to mdellweg/foreman-ansible-modules that referenced this issue Jun 28, 2021
mdellweg added a commit to mdellweg/foreman-ansible-modules that referenced this issue Jun 28, 2021
mdellweg added a commit to mdellweg/foreman-ansible-modules that referenced this issue Jul 17, 2021
mdellweg added a commit to mdellweg/foreman-ansible-modules that referenced this issue Jul 17, 2021
@mdellweg
Copy link
Member

@achevalet can you confirm that this PR fixes the problem?

mdellweg added a commit to mdellweg/foreman-ansible-modules that referenced this issue Aug 25, 2021
evgeni pushed a commit to evgeni/foreman-ansible-modules that referenced this issue Aug 27, 2021
@evgeni
Copy link
Member

evgeni commented Aug 27, 2021

@achevalet would you have time to look at #1281 and whether that fixes your issue? I think it should, but one never knows ;)

@achevalet
Copy link
Contributor Author

Hey, my apologies for the delayed response, yes I will check it out next week and let you know. Thanks for that one!

@achevalet
Copy link
Contributor Author

Just tested it and I confirm that it works like a charm! We can update puppetclasses and/or description in the same task 👍

@evgeni
Copy link
Member

evgeni commented Sep 17, 2021

#1281 is merged

@evgeni evgeni closed this as completed Sep 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants