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

Unable to unset compute_profile in hostgroups via ansible #969

Closed
cmeissner opened this issue Sep 22, 2020 · 9 comments · Fixed by #1016
Closed

Unable to unset compute_profile in hostgroups via ansible #969

cmeissner opened this issue Sep 22, 2020 · 9 comments · Fixed by #1016
Assignees
Labels

Comments

@cmeissner
Copy link
Member

cmeissner commented Sep 22, 2020

SUMMARY

It's not possible to unset compute_profile field via ansible. If we set compute_profile either via Ui or via Ansible we have only the possibility to unset the compute_profile field to null via UI not via ansible.

ISSUE TYPE
  • Bug Report
ANSIBLE VERSION
ansible 2.9.10
KATELLO/FOREMAN VERSION
2.1.2
APYPIE VERSION
Version: 0.2.2
STEPS TO REPRODUCE
  1. Create a hostgroup with compute_profile set.
  2. Set compute_profile in ansible module call to None
EXPECTED RESULTS

Compute profile in UI should show Inherit ... or is empty

ACTUAL RESULTS

Ansible runs into the following error:

fatal: [localhost]: FAILED! => {"changed": false, "msg": "Found no results while searching for compute_profiles with name=\"\""}
@cmeissner
Copy link
Member Author

We need to set [] (empty list). So it's not a bug but a feature request instead. It would be great if there can set None to reset a parameter.

@mdellweg
Copy link
Member

mdellweg commented Oct 1, 2020

I believe that is impossible, as ansible gives you None if a parameter was not set, in which case we already interpret "don't change". So providing [], {} or "" is really the only way to specify "empty".

@mdellweg
Copy link
Member

mdellweg commented Oct 1, 2020

however, documentation can always be improved. hint

@cmeissner
Copy link
Member Author

cmeissner commented Oct 6, 2020

I dig a bit on this issue and it still exists for string parameters.

I used the following playbook to reproduce the issue:

---
- hosts: foreman
  connection: local
  gather_facts: no
  vars:
    foreman_admin: admin
    foreman_validate_certs: False
    foreman_server_url: "https://foreman.example.net"

  tasks:
    - name: create hostgroup
      theforeman.foreman.hostgroup:
        username: "{{ foreman_admin }}"
        password: "{{ foreman_admin_password }}"
        server_url: "{{ foreman_server_url }}"
        validate_certs: "{{ foreman_validate_certs }}"
        name: Test
        locations:
          - 0193
        organizations:
          - SPOCK
        parameters:
          - name: foo
            parameter_type: string
            value: bar
        compute_profile: generic
        state: present

    - name: remove compute_profile from hostgroup
      theforeman.foreman.hostgroup:
        username: "{{ foreman_admin }}"
        password: "{{ foreman_admin_password }}"
        server_url: "{{ foreman_server_url }}"
        validate_certs: "{{ foreman_validate_certs }}"
        name: Test
        locations:
          - 0193
        organizations:
          - SPOCK
        parameters:
          - name: foo
            parameter_type: string
            value: bar
        compute_profile: ''
        state: present
      ignore_errors: True

    - name: remove organizations from hostgroup
      theforeman.foreman.hostgroup:
        username: "{{ foreman_admin }}"
        password: "{{ foreman_admin_password }}"
        server_url: "{{ foreman_server_url }}"
        validate_certs: "{{ foreman_validate_certs }}"
        name: Test
        organizations: []
        state: present
      ignore_errors: True

    - name: remove locations from hostgroup
      theforeman.foreman.hostgroup:
        username: "{{ foreman_admin }}"
        password: "{{ foreman_admin_password }}"
        server_url: "{{ foreman_server_url }}"
        validate_certs: "{{ foreman_validate_certs }}"
        name: Test
        locations: []
        state: present
      ignore_errors: True

    - name: add architecture to hostgroup
      theforeman.foreman.hostgroup:
        username: "{{ foreman_admin }}"
        password: "{{ foreman_admin_password }}"
        server_url: "{{ foreman_server_url }}"
        validate_certs: "{{ foreman_validate_certs }}"
        name: Test
        architecture: amd64
        state: present
      ignore_errors: True

    - name: remove architecture from hostgroup
      theforeman.foreman.hostgroup:
        username: "{{ foreman_admin }}"
        password: "{{ foreman_admin_password }}"
        server_url: "{{ foreman_server_url }}"
        validate_certs: "{{ foreman_validate_certs }}"
        name: Test
        architecture: ''
        state: present
      ignore_errors: True

    - name: remove hostgroup
      theforeman.foreman.hostgroup:
        username: "{{ foreman_admin }}"
        password: "{{ foreman_admin_password }}"
        server_url: "https://foreman.example.net"
        validate_certs: "{{ foreman_validate_certs }}"
        name: Test
        state: absent
      ignore_errors: True

it leads me to the following normal output:

$ ansible-playbook --vault-password-file ansible-vault-env-pass -i inventory tests/unset_stuff.yml 

PLAY [spock_foreman] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************

TASK [create hostgroup] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
changed: [localhost]

TASK [remove compute_profile from hostgroup] ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Found no results while searching for compute_profiles with name=\"\""}
...ignoring

TASK [remove organizations from hostgroup] ******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
changed: [localhost]

TASK [remove locations from hostgroup] **********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
changed: [localhost]

TASK [add architecture to hostgroup] ************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
changed: [localhost]

TASK [remove architecture from hostgroup] *******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
fatal: [localhost]: FAILED! => {"changed": false, "msg": "Found no results while searching for architectures with name=\"\""}
...ignoring

TASK [remove hostgroup] *************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
changed: [localhost]

PLAY RECAP **************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************
localhost                  : ok=7    changed=5    unreachable=0    failed=0    skipped=0    rescued=0    ignored=2

Debug output for the misbehaving tasks as followed:

fatal: [localhost]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "architecture": null,
            "compute_profile": "",
            "compute_resource": null,
            "config_groups": null,
            "content_source": null,
            "content_view": null,
            "description": null,
            "domain": null,
            "environment": null,
            "kickstart_repository": null,
            "lifecycle_environment": null,
            "locations": [
                "0193"
            ],
            "medium": null,
            "name": "Test",
            "openscap_proxy": null,
            "operatingsystem": null,
            "organization": null,
            "organizations": [
                "SPOCK"
            ],
            "parameters": [
                {
                    "name": "foo",
                    "parameter_type": "string",
                    "value": "bar"
                }
            ],
            "parent": null,
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "ptable": null,
            "puppet_ca_proxy": null,
            "puppet_proxy": null,
            "puppetclasses": null,
            "pxe_loader": null,
            "realm": null,
            "root_pass": null,
            "server_url": "https://foreman.example.net",
            "state": "present",
            "subnet": null,
            "subnet6": null,
            "updated_name": null,
            "username": "admin",
            "validate_certs": false
        }
    },
    "msg": "Found no results while searching for compute_profiles with name=\"\""
}
...ignoring

and

fatal: [localhost]: FAILED! => {
    "changed": false,
    "invocation": {
        "module_args": {
            "architecture": "",
            "compute_profile": null,
            "compute_resource": null,
            "config_groups": null,
            "content_source": null,
            "content_view": null,
            "description": null,
            "domain": null,
            "environment": null,
            "kickstart_repository": null,
            "lifecycle_environment": null,
            "locations": null,
            "medium": null,
            "name": "Test",
            "openscap_proxy": null,
            "operatingsystem": null,
            "organization": null,
            "organizations": null,
            "parameters": null,
            "parent": null,
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER",
            "ptable": null,
            "puppet_ca_proxy": null,
            "puppet_proxy": null,
            "puppetclasses": null,
            "pxe_loader": null,
            "realm": null,
            "root_pass": null,
            "server_url": "https://foreman.example.net",
            "state": "present",
            "subnet": null,
            "subnet6": null,
            "updated_name": null,
            "username": "admin",
            "validate_certs": false
        }
    },
    "msg": "Found no results while searching for architectures with name=\"\""
}
...ignoring

This shows that it's not possible to unset string parameters with '' as. Also "" leads to the very same result.

@cmeissner cmeissner reopened this Oct 6, 2020
@evgeni
Copy link
Member

evgeni commented Oct 6, 2020

Yeah, I can see how that won't work for non-list-type params…

We might need to specialcase '' (empty string) for this to work. Which is ugly, but oh well…

@cmeissner
Copy link
Member Author

I added the following tasks:

    - name: add description to hostgroup
      theforeman.foreman.hostgroup:
        username: "{{ foreman_admin }}"
        password: "{{ foreman_admin_password }}"
        server_url: "{{ foreman_server_url }}"
        validate_certs: "{{ foreman_validate_certs }}"
        name: Test
        description: 'Test'
        state: present
      ignore_errors: True

    - name: remove description from hostgroup
      theforeman.foreman.hostgroup:
        username: "{{ foreman_admin }}"
        password: "{{ foreman_admin_password }}"
        server_url: "{{ foreman_server_url }}"
        validate_certs: "{{ foreman_validate_certs }}"
        name: Test
        description: ''
        state: present
      ignore_errors: True

and this works. Description is not a selection in UI. So no request for entities have to be done I guess.

@evgeni
Copy link
Member

evgeni commented Oct 6, 2020

Yeah, it only fails for parameters that refer to other entities. So e.g. a domain referring to a subnet, or a hostgroup refering to an architecture.

If you look at the code of the modules, it's those which have type='entity'

@evgeni
Copy link
Member

evgeni commented Oct 7, 2020

Do you feel like experimenting?

diff --git plugins/module_utils/foreman_helper.py plugins/module_utils/foreman_helper.py
index abb23e77..ae2a4e46 100644
--- plugins/module_utils/foreman_helper.py
+++ plugins/module_utils/foreman_helper.py
@@ -622,6 +622,8 @@ class ForemanAnsibleModule(AnsibleModule):
         return result
 
     def find_resource_by(self, resource, search_field, value, **kwargs):
+        if not value and kwargs.get('failsafe', False):
+            return None
         search = '{0}{1}"{2}"'.format(search_field, kwargs.pop('search_operator', '='), value)
         return self.find_resource(resource, search, **kwargs)
 

This might do it, but completely untested.

@cmeissner
Copy link
Member Author

cmeissner commented Oct 7, 2020

@evgeni I applied your patch to my work tree but unfortunately it doesn't help out. Same errors.

@evgeni evgeni linked a pull request Oct 19, 2020 that will close this issue
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants