def test_build_copy_symlink_target_inside_collection(collection_input): input_dir = collection_input[0] os.makedirs(os.path.join(input_dir, 'playbooks', 'roles')) roles_link = os.path.join(input_dir, 'playbooks', 'roles', 'linked') roles_target = os.path.join(input_dir, 'roles', 'linked') roles_target_tasks = os.path.join(roles_target, 'tasks') os.makedirs(roles_target_tasks) with open(os.path.join(roles_target_tasks, 'main.yml'), 'w+') as tasks_main: tasks_main.write("---\n- hosts: localhost\n tasks:\n - ping:") tasks_main.flush() os.symlink(roles_target, roles_link) actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection') linked_entries = [ e for e in actual['files'] if e['name'].startswith('playbooks/roles/linked') ] assert len(linked_entries) == 3 assert linked_entries[0]['name'] == 'playbooks/roles/linked' assert linked_entries[0]['ftype'] == 'dir' assert linked_entries[1]['name'] == 'playbooks/roles/linked/tasks' assert linked_entries[1]['ftype'] == 'dir' assert linked_entries[2]['name'] == 'playbooks/roles/linked/tasks/main.yml' assert linked_entries[2]['ftype'] == 'file' assert linked_entries[2][ 'chksum_sha256'] == '9c97a1633c51796999284c62236b8d5462903664640079b80c37bf50080fcbc3'
def test_build_copy_symlink_target_inside_collection(collection_input): input_dir = collection_input[0] os.makedirs(os.path.join(input_dir, 'playbooks', 'roles')) roles_link = os.path.join(input_dir, 'playbooks', 'roles', 'linked') roles_target = os.path.join(input_dir, 'roles', 'linked') roles_target_tasks = os.path.join(roles_target, 'tasks') os.makedirs(roles_target_tasks) with open(os.path.join(roles_target_tasks, 'main.yml'), 'w+') as tasks_main: tasks_main.write("---\n- hosts: localhost\n tasks:\n - ping:") tasks_main.flush() os.symlink(roles_target, roles_link) actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection', []) linked_entries = [ e for e in actual['files'] if e['name'].startswith('playbooks/roles/linked') ] assert len(linked_entries) == 1 assert linked_entries[0]['name'] == 'playbooks/roles/linked' assert linked_entries[0]['ftype'] == 'dir'
def test_build_ignore_older_release_in_root(collection_input, monkeypatch): input_dir = collection_input[0] mock_display = MagicMock() monkeypatch.setattr(Display, 'vvv', mock_display) # This is expected to be ignored because it is in the root collection dir. release_file = os.path.join(input_dir, 'namespace-collection-0.0.0.tar.gz') # This is not expected to be ignored because it is not in the root collection dir. fake_release_file = os.path.join(input_dir, 'plugins', 'namespace-collection-0.0.0.tar.gz') for filename in [release_file, fake_release_file]: with open(filename, 'w+') as file_obj: file_obj.write('random') file_obj.flush() actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection') assert actual['format'] == 1 plugin_release_found = False for manifest_entry in actual['files']: assert manifest_entry['name'] != 'namespace-collection-0.0.0.tar.gz' if manifest_entry[ 'name'] == 'plugins/namespace-collection-0.0.0.tar.gz': plugin_release_found = True assert plugin_release_found assert mock_display.call_count == 1 assert mock_display.mock_calls[0][1][ 0] == "Skipping '%s' for collection build" % to_text(release_file)
def test_build_ignore_files_and_folders(collection_input, monkeypatch): input_dir = collection_input[0] mock_display = MagicMock() monkeypatch.setattr(Display, 'vvv', mock_display) git_folder = os.path.join(input_dir, '.git') retry_file = os.path.join(input_dir, 'ansible.retry') os.makedirs(git_folder) with open(retry_file, 'w+') as ignore_file: ignore_file.write('random') ignore_file.flush() actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection') assert actual['format'] == 1 for manifest_entry in actual['files']: assert manifest_entry['name'] not in [ '.git', 'ansible.retry', 'galaxy.yml' ] expected_msgs = [ "Skipping '%s' for collection build" % to_text(retry_file), "Skipping '%s' for collection build" % to_text(git_folder), ] assert mock_display.call_count == 2 assert mock_display.mock_calls[0][1][0] in expected_msgs assert mock_display.mock_calls[1][1][0] in expected_msgs
def test_build_ignore_patterns(collection_input, monkeypatch): input_dir = collection_input[0] mock_display = MagicMock() monkeypatch.setattr(Display, 'vvv', mock_display) actual = collection._build_files_manifest( to_bytes(input_dir), 'namespace', 'collection', ['*.md', 'plugins/action', 'playbooks/*.j2']) assert actual['format'] == 1 expected_missing = [ 'README.md', 'docs/My Collection.md', 'plugins/action', 'playbooks/templates/test.conf.j2', 'playbooks/templates/subfolder/test.conf.j2', ] # Files or dirs that are close to a match but are not, make sure they are present expected_present = [ 'docs', 'roles/common/templates/test.conf.j2', 'roles/common/templates/subfolder/test.conf.j2', ] actual_files = [e['name'] for e in actual['files']] for m in expected_missing: assert m not in actual_files for p in expected_present: assert p in actual_files expected_msgs = [ "Skipping '%s/galaxy.yml' for collection build" % to_text(input_dir), "Skipping '%s/README.md' for collection build" % to_text(input_dir), "Skipping '%s/docs/My Collection.md' for collection build" % to_text(input_dir), "Skipping '%s/plugins/action' for collection build" % to_text(input_dir), "Skipping '%s/playbooks/templates/test.conf.j2' for collection build" % to_text(input_dir), "Skipping '%s/playbooks/templates/subfolder/test.conf.j2' for collection build" % to_text(input_dir), ] assert mock_display.call_count == len(expected_msgs) assert mock_display.mock_calls[0][1][0] in expected_msgs assert mock_display.mock_calls[1][1][0] in expected_msgs assert mock_display.mock_calls[2][1][0] in expected_msgs assert mock_display.mock_calls[3][1][0] in expected_msgs assert mock_display.mock_calls[4][1][0] in expected_msgs assert mock_display.mock_calls[5][1][0] in expected_msgs
def test_build_ignore_symlink_target_outside_collection(collection_input, monkeypatch): input_dir, outside_dir = collection_input mock_display = MagicMock() monkeypatch.setattr(Display, 'warning', mock_display) link_path = os.path.join(input_dir, 'plugins', 'connection') os.symlink(outside_dir, link_path) actual = collection._build_files_manifest(to_bytes(input_dir), 'namespace', 'collection', []) for manifest_entry in actual['files']: assert manifest_entry['name'] != 'plugins/connection' assert mock_display.call_count == 1 assert mock_display.mock_calls[0][1][0] == "Skipping '%s' as it is a symbolic link to a directory outside " \ "the collection" % to_text(link_path)
import json import os from ansible.galaxy.collection import _build_files_manifest from ansible.galaxy.collection import _build_manifest from ansible.galaxy.collection import _get_galaxy_yml from ansible.module_utils._text import to_bytes galaxy = _get_galaxy_yml('galaxy.yml') b_here = to_bytes(os.path.abspath('.')) with open('MANIFEST.json', 'w+') as f: json.dump( _build_manifest(**galaxy), f, indent=4, sort_keys=True, ) with open('FILES.json', 'w+') as f: json.dump( _build_files_manifest( b_here, galaxy['namespace'], galaxy['name'], galaxy['build_ignore'], ), f, indent=4, sort_keys=True, )