diff --git a/Makefile b/Makefile index 7f4a957a4e..78d5808a41 100644 --- a/Makefile +++ b/Makefile @@ -393,7 +393,7 @@ symlink_collection: ln -s $(shell pwd)/awx_collection $(COLLECTION_INSTALL) build_collection: - ansible-playbook -i localhost, awx_collection/tools/template_galaxy.yml -e collection_package=$(COLLECTION_PACKAGE) -e collection_namespace=$(COLLECTION_NAMESPACE) -e collection_version=$(VERSION) + ansible-playbook -i localhost, awx_collection/tools/template_galaxy.yml -e collection_package=$(COLLECTION_PACKAGE) -e collection_namespace=$(COLLECTION_NAMESPACE) -e collection_version=$(VERSION) -e '{"awx_template_version":false}' ansible-galaxy collection build awx_collection --force --output-path=awx_collection install_collection: build_collection diff --git a/awx_collection/plugins/doc_fragments/auth.py b/awx_collection/plugins/doc_fragments/auth.py index 9018f8f26d..bf0ea28832 100644 --- a/awx_collection/plugins/doc_fragments/auth.py +++ b/awx_collection/plugins/doc_fragments/auth.py @@ -39,6 +39,7 @@ options: tower_config_file: description: - Path to the Tower or AWX config file. + - If provided, the other locations for config files will not be considered. type: path notes: diff --git a/awx_collection/plugins/module_utils/tower_api.py b/awx_collection/plugins/module_utils/tower_api.py index bba81410c1..7029922a4e 100644 --- a/awx_collection/plugins/module_utils/tower_api.py +++ b/awx_collection/plugins/module_utils/tower_api.py @@ -33,7 +33,7 @@ class ItemNotDefined(Exception): class TowerModule(AnsibleModule): # This gets set by the make process so whatever is in here is irrelevant - _COLLECTION_VERSION = "11.1.0" + _COLLECTION_VERSION = "devel" _COLLECTION_TYPE = "awx" # This maps the collections type (awx/tower) to the values returned by the API # Those values can be found in awx/api/generics.py line 204 @@ -114,14 +114,6 @@ class TowerModule(AnsibleModule): local_dir = split(local_dir)[0] config_files.insert(2, join(local_dir, ".{0}".format(self.config_name))) - for config_file in config_files: - if exists(config_file) and not isdir(config_file): - # Only throw a formatting error if the file exists and is not a directory - try: - self.load_config(config_file) - except ConfigFileException: - self.fail_json('The config file {0} is not properly formatted'.format(config_file)) - # If we have a specified tower config, load it if self.params.get('tower_config_file'): duplicated_params = [] @@ -139,6 +131,14 @@ class TowerModule(AnsibleModule): except ConfigFileException as cfe: # Since we were told specifically to load this we want it to fail if we have an error self.fail_json(msg=cfe) + else: + for config_file in config_files: + if exists(config_file) and not isdir(config_file): + # Only throw a formatting error if the file exists and is not a directory + try: + self.load_config(config_file) + except ConfigFileException: + self.fail_json('The config file {0} is not properly formatted'.format(config_file)) def load_config(self, config_path): # Validate the config file is an actual file diff --git a/awx_collection/test/awx/conftest.py b/awx_collection/test/awx/conftest.py index a6f102554f..5b08f220a7 100644 --- a/awx_collection/test/awx/conftest.py +++ b/awx_collection/test/awx/conftest.py @@ -108,7 +108,7 @@ def run_module(request, collection_import): sanitize_dict(py_data) resp._content = bytes(json.dumps(django_response.data), encoding='utf8') resp.status_code = django_response.status_code - resp.headers = {'X-API-Product-Name': 'AWX', 'X-API-Product-Version': '11.0.0'} + resp.headers = {'X-API-Product-Name': 'AWX', 'X-API-Product-Version': 'devel'} if request.config.getoption('verbose') > 0: logger.info( diff --git a/awx_collection/test/awx/test_job_template.py b/awx_collection/test/awx/test_job_template.py index 2f468edd55..4b480ed45d 100644 --- a/awx_collection/test/awx/test_job_template.py +++ b/awx_collection/test/awx/test_job_template.py @@ -4,7 +4,6 @@ __metaclass__ = type import pytest from awx.main.models import ActivityStream, JobTemplate, Job, NotificationTemplate -from unittest import mock @pytest.mark.django_db @@ -162,9 +161,9 @@ def test_job_template_with_survey_encrypted_default(run_module, admin_user, proj assert result.get('changed', False), result # not actually desired, but assert for sanity - silence_warning.assert_has_calls( - [mock.call("The field survey_spec of job_template {0} has encrypted data and " - "may inaccurately report task is changed.".format(result['id']))]) + silence_warning.assert_called_once_with( + "The field survey_spec of job_template {0} has encrypted data and " + "may inaccurately report task is changed.".format(result['id'])) @pytest.mark.django_db diff --git a/awx_collection/test/awx/test_module_utils.py b/awx_collection/test/awx/test_module_utils.py index fca370ff81..3c3cdf61c8 100644 --- a/awx_collection/test/awx/test_module_utils.py +++ b/awx_collection/test/awx/test_module_utils.py @@ -91,3 +91,21 @@ def test_duplicate_config(collection_import, silence_warning): 'tower_config_file. Precedence may be unstable, ' 'we suggest either using config file or params.' ) + + +def test_no_templated_values(collection_import): + """This test corresponds to replacements done by + awx_collection/tools/roles/template_galaxy/tasks/main.yml + Those replacements should happen at build time, so they should not be + checked into source. + """ + TowerModule = collection_import('plugins.module_utils.tower_api').TowerModule + assert TowerModule._COLLECTION_VERSION == "devel", ( + 'The collection version is templated when the collection is built ' + 'and the code should retain the placeholder of "devel".' + ) + InventoryModule = collection_import('plugins.inventory.tower').InventoryModule + assert InventoryModule.NAME == 'awx.awx.tower', ( + 'The inventory plugin FQCN is templated when the collection is built ' + 'and the code should retain the default of awx.awx.' + ) diff --git a/awx_collection/test/awx/test_project.py b/awx_collection/test/awx/test_project.py index c5f0ab718d..9ef1596d3f 100644 --- a/awx_collection/test/awx/test_project.py +++ b/awx_collection/test/awx/test_project.py @@ -3,8 +3,6 @@ __metaclass__ = type import pytest -from unittest import mock - from awx.main.models import Project @@ -18,9 +16,9 @@ def test_create_project(run_module, admin_user, organization, silence_warning): wait=False, scm_update_cache_timeout=5 ), admin_user) - silence_warning.assert_has_calls( - [mock.call('scm_update_cache_timeout will be ignored since scm_update_on_launch ' - 'was not set to true')]) + silence_warning.assert_called_once_with( + 'scm_update_cache_timeout will be ignored since scm_update_on_launch ' + 'was not set to true') assert result.pop('changed', None), result diff --git a/awx_collection/test/awx/test_user.py b/awx_collection/test/awx/test_user.py index 51c47b6755..db705bd5be 100644 --- a/awx_collection/test/awx/test_user.py +++ b/awx_collection/test/awx/test_user.py @@ -41,6 +41,6 @@ def test_password_no_op_warning(run_module, admin_user, mock_auth_stuff, silence assert result.get('changed') # not actually desired, but assert for sanity - silence_warning.assert_has_calls( - [mock.call("The field password of user {0} has encrypted data and " - "may inaccurately report task is changed.".format(result['id']))]) + silence_warning.assert_called_once_with( + "The field password of user {0} has encrypted data and " + "may inaccurately report task is changed.".format(result['id'])) diff --git a/awx_collection/tools/roles/template_galaxy/tasks/main.yml b/awx_collection/tools/roles/template_galaxy/tasks/main.yml index 77a835602f..c8d6f0fff3 100644 --- a/awx_collection/tools/roles/template_galaxy/tasks/main.yml +++ b/awx_collection/tools/roles/template_galaxy/tasks/main.yml @@ -2,13 +2,15 @@ - name: Set the collection version in the tower_api.py file replace: path: "{{ collection_path }}/plugins/module_utils/tower_api.py" - regexp: '^ _COLLECTION_VERSION =.*' + regexp: '^ _COLLECTION_VERSION = "devel"' replace: ' _COLLECTION_VERSION = "{{ collection_version }}"' + when: + - "awx_template_version | default(True)" - name: Set the collection type in the tower_api.py file replace: path: "{{ collection_path }}/plugins/module_utils/tower_api.py" - regexp: '^ _COLLECTION_TYPE =.*' + regexp: '^ _COLLECTION_TYPE = "awx"' replace: ' _COLLECTION_TYPE = "{{ collection_namespace }}"' - name: Do file content replacements for non-default namespace or package name