diff --git a/scripts/emit_releases_file/emit_releases_file.py b/scripts/emit_releases_file/emit_releases_file.py index f18f417f3..f6c936d75 100644 --- a/scripts/emit_releases_file/emit_releases_file.py +++ b/scripts/emit_releases_file/emit_releases_file.py @@ -43,8 +43,8 @@ def load_featureset_file(featureset_file): def get_dlrn_hash(release, hash_name, retries=10): logger = logging.getLogger('emit-releases') full_hash_pattern = re.compile('[a-z,0-9]{40}_[a-z,0-9]{8}') - repo_url = ('https://trunk.rdoproject.org/centos7-%s/%s/delorean.repo' - % (release, hash_name)) + repo_url = ('https://trunk.rdoproject.org/centos7-%s/%s/delorean.repo' % + (release, hash_name)) for retry_num in range(retries): repo_file = None # Timeout if initial connection is longer than default @@ -155,6 +155,28 @@ def shim_convert_old_release_names(releases_names): return releases_names +def write_releases_dictionary_to_bash(releases_dictionary, bash_file_name): + logger = logging.getLogger('emit-releases') + # Make it deterministic, expected constants in the proper order + try: + bash_script = '''#!/bin/env bash +export UNDERCLOUD_INSTALL_RELEASE="{undercloud_install_release}" +export UNDERCLOUD_INSTALL_HASH="{undercloud_install_hash}" +export UNDERCLOUD_TARGET_RELEASE="{undercloud_target_release}" +export UNDERCLOUD_TARGET_HASH="{undercloud_target_hash}" +export OVERCLOUD_DEPLOY_RELEASE="{overcloud_deploy_release}" +export OVERCLOUD_DEPLOY_HASH="{overcloud_deploy_hash}" +export OVERCLOUD_TARGET_RELEASE="{overcloud_target_release}" +export OVERCLOUD_TARGET_HASH="{overcloud_target_hash}" +'''.format(**releases_dictionary) + with open(bash_file_name, 'w') as bash_file: + bash_file.write(bash_script) + except Exception: + logger.exception("Writting releases dictionary") + return False + return True + + if __name__ == '__main__': default_log_file = '{}.log'.format(os.path.basename(__file__)) @@ -193,5 +215,8 @@ if __name__ == '__main__': releases_dictionary = compose_releases_dictionary(args.stable_release, featureset) - releases_dictionary = shim_convert_old_release_names( - releases_dictionary) + releases_dictionary = shim_convert_old_release_names(releases_dictionary) + + if not write_releases_dictionary_to_bash( + releases_dictionary, args.output_file): + exit(1) diff --git a/scripts/emit_releases_file/test_get_dlrn_hash.py b/scripts/emit_releases_file/test_get_dlrn_hash.py index 2525fb190..d94cf7ca8 100644 --- a/scripts/emit_releases_file/test_get_dlrn_hash.py +++ b/scripts/emit_releases_file/test_get_dlrn_hash.py @@ -7,18 +7,20 @@ import pytest @mock.patch('requests.get') def test_get_dlrn_hash(mock_get): mock_response = mock.Mock() - mock_response.content = ('[delorean]\nname=delorean-openstack-nova-81c23c04' - '7e8e0fc03b54164921f49fdb4103202c\nbaseurl=https:/' - '/trunk.rdoproject.org/centos7/81/c2/81c23c047e8e0' - 'fc03b54164921f49fdb4103202c_b333f915\nenabled=1\n' - 'gpgcheck=0\npriority=1') + mock_response.content = ( + '[delorean]\nname=delorean-openstack-nova-81c23c04' + '7e8e0fc03b54164921f49fdb4103202c\nbaseurl=https:/' + '/trunk.rdoproject.org/centos7/81/c2/81c23c047e8e0' + 'fc03b54164921f49fdb4103202c_b333f915\nenabled=1\n' + 'gpgcheck=0\npriority=1') release = 'master' hash_name = 'current-tripleo' - repo_url = ('https://trunk.rdoproject.org/centos7-%s/%s/delorean.repo' - % (release, hash_name)) + repo_url = ('https://trunk.rdoproject.org/centos7-%s/%s/delorean.repo' % + (release, hash_name)) mock_get.return_value = mock_response - assert (get_dlrn_hash(release, hash_name) == - '81c23c047e8e0fc03b54164921f49fdb4103202c_b333f915') + assert (get_dlrn_hash( + release, + hash_name) == '81c23c047e8e0fc03b54164921f49fdb4103202c_b333f915') mock_get.assert_called_once_with(repo_url, timeout=(3.05, 27)) diff --git a/scripts/emit_releases_file/test_write_bash_script.py b/scripts/emit_releases_file/test_write_bash_script.py new file mode 100644 index 000000000..e074d5bf2 --- /dev/null +++ b/scripts/emit_releases_file/test_write_bash_script.py @@ -0,0 +1,68 @@ +from emit_releases_file import write_releases_dictionary_to_bash + +import os +import mock +from mock import mock_open +from six import PY2 + +import pytest + +if PY2: + BUILTINS_OPEN = "__builtin__.open" +else: + BUILTINS_OPEN = "builtins.open" + + +def test_empty_relases_dictionary_fails(): + assert (not write_releases_dictionary_to_bash({}, "")) + + +@pytest.fixture +def releases_dictionary(): + return { + 'undercloud_install_release': 'queens', + 'undercloud_install_hash': 'current-tripleo', + 'undercloud_target_release': 'master', + 'undercloud_target_hash': 'current-tripleo', + 'overcloud_deploy_release': 'master', + 'overcloud_deploy_hash': 'current-tripleo', + 'overcloud_target_release': 'master', + 'overcloud_target_hash': 'current-tripleo', + } + + +@pytest.mark.parametrize('deleted_key', [ + 'undercloud_install_release', + 'undercloud_install_hash', + 'undercloud_target_release', + 'undercloud_target_hash', + 'overcloud_deploy_release', + 'overcloud_deploy_hash', + 'overcloud_target_release', + 'overcloud_target_hash', +]) +def test_missing_key_fails(releases_dictionary, deleted_key): + wrong_releases_dictionary = releases_dictionary.pop(deleted_key) + assert (not write_releases_dictionary_to_bash(wrong_releases_dictionary, + "")) + + +@mock.patch(BUILTINS_OPEN, new_callable=mock_open) +def test_open_exception_fails(mock, releases_dictionary): + bash_script = '/foo/bar.sh' + mock.side_effect = IOError + assert (not write_releases_dictionary_to_bash(releases_dictionary, + bash_script)) + + +@mock.patch(BUILTINS_OPEN, new_callable=mock_open) +def test_output_is_sourceable(mock, releases_dictionary): + bash_script = '/foo/bar.sh' + assert (write_releases_dictionary_to_bash(releases_dictionary, + bash_script)) + mock.assert_called_once_with(bash_script, 'w') + handle = mock() + args, _ = handle.write.call_args + written_content = args[0] + # TODO: check environment variables + assert (0 == os.system(written_content))