| ''' |
| Licensed to the Apache Software Foundation (ASF) under one |
| or more contributor license agreements. See the NOTICE file |
| distributed with this work for additional information |
| regarding copyright ownership. The ASF licenses this file |
| to you under the Apache License, Version 2.0 (the |
| "License"); you may not use this file except in compliance |
| with the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ''' |
| |
| import os, sys |
| import tempfile |
| from unittest import TestCase |
| from mock.mock import patch, MagicMock |
| from only_for_platform import get_platform, not_for_platform, PLATFORM_WINDOWS |
| |
| from ambari_commons.os_check import OSCheck |
| |
| from resource_management.core.environment import Environment |
| from resource_management.core.source import InlineTemplate |
| from resource_management.core.system import System |
| from resource_management.libraries.resources.repository import Repository |
| |
| if get_platform() != PLATFORM_WINDOWS: |
| from resource_management.libraries.providers import repository |
| |
| class DummyTemplate(object): |
| |
| def __init__(self, name, extra_imports=[], **kwargs): |
| self._template = InlineTemplate(DummyTemplate._inline_text, extra_imports, **kwargs) |
| self.context = self._template.context |
| self.name = name |
| |
| def get_content(self): |
| self.content = self._template.get_content() |
| return self.content |
| |
| @classmethod |
| def create(cls, text): |
| cls._inline_text = text |
| return cls |
| |
| DEBIAN_DEFAUTL_TEMPLATE = "{{package_type}} {{base_url}} {{components}}\n" |
| RHEL_SUSE_DEFAULT_TEMPLATE ="""[{{repo_id}}] |
| name={{repo_id}} |
| {% if mirror_list %}mirrorlist={{mirror_list}}{% else %}baseurl={{base_url}}{% endif %} |
| |
| path=/ |
| enabled=1 |
| gpgcheck=0 |
| """ |
| |
| |
| class TestRepositoryResource(TestCase): |
| @patch.object(OSCheck, "is_suse_family") |
| @patch.object(OSCheck, "is_ubuntu_family") |
| @patch.object(OSCheck, "is_redhat_family") |
| @patch("resource_management.libraries.providers.repository.File") |
| @patch.object(System, "os_family", new='redhat') |
| def test_create_repo_redhat(self, file_mock, |
| is_redhat_family, is_ubuntu_family, is_suse_family): |
| is_redhat_family.return_value = True |
| is_ubuntu_family.return_value = False |
| is_suse_family.return_value = False |
| with Environment('/') as env: |
| with patch.object(repository, "__file__", new='/ambari/test/repo/dummy/path/file'): |
| Repository('hadoop', |
| base_url='http://download.base_url.org/rpm/', |
| mirror_list='https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| repo_file_name='Repository', |
| repo_template=RHEL_SUSE_DEFAULT_TEMPLATE) |
| |
| self.assertTrue('hadoop' in env.resources['Repository']) |
| defined_arguments = env.resources['Repository']['hadoop'].arguments |
| expected_arguments = {'repo_template': RHEL_SUSE_DEFAULT_TEMPLATE, |
| 'base_url': 'http://download.base_url.org/rpm/', |
| 'mirror_list': 'https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| 'repo_file_name': 'Repository'} |
| expected_template_arguments = {'base_url': 'http://download.base_url.org/rpm/', |
| 'mirror_list': 'https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| 'repo_file_name': 'Repository'} |
| |
| self.assertEqual(defined_arguments, expected_arguments) |
| self.assertEqual(file_mock.call_args[0][0], '/etc/yum.repos.d/Repository.repo') |
| |
| template_item = file_mock.call_args[1]['content'] |
| template = str(template_item.name) |
| expected_template_arguments.update({'repo_id': 'hadoop'}) |
| |
| self.assertEqual(expected_template_arguments, template_item.context._dict) |
| self.assertEqual(RHEL_SUSE_DEFAULT_TEMPLATE, template) |
| |
| |
| @patch.object(OSCheck, "is_suse_family") |
| @patch.object(OSCheck, "is_ubuntu_family") |
| @patch.object(OSCheck, "is_redhat_family") |
| @patch.object(System, "os_family", new='suse') |
| @patch("resource_management.libraries.providers.repository.File") |
| def test_create_repo_suse(self, file_mock, |
| is_redhat_family, is_ubuntu_family, is_suse_family): |
| is_redhat_family.return_value = False |
| is_ubuntu_family.return_value = False |
| is_suse_family.return_value = True |
| with Environment('/') as env: |
| with patch.object(repository, "__file__", new='/ambari/test/repo/dummy/path/file'): |
| Repository('hadoop', |
| base_url='http://download.base_url.org/rpm/', |
| mirror_list='https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| repo_template = RHEL_SUSE_DEFAULT_TEMPLATE, |
| repo_file_name='Repository') |
| |
| self.assertTrue('hadoop' in env.resources['Repository']) |
| defined_arguments = env.resources['Repository']['hadoop'].arguments |
| expected_arguments = {'repo_template': RHEL_SUSE_DEFAULT_TEMPLATE, |
| 'mirror_list': 'https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| 'base_url': 'http://download.base_url.org/rpm/', |
| 'repo_file_name': 'Repository'} |
| expected_template_arguments = {'mirror_list': 'https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| 'base_url': 'http://download.base_url.org/rpm/', |
| 'repo_file_name': 'Repository'} |
| |
| self.assertEqual(defined_arguments, expected_arguments) |
| self.assertEqual(file_mock.call_args[0][0], '/etc/zypp/repos.d/Repository.repo') |
| |
| template_item = file_mock.call_args[1]['content'] |
| template = str(template_item.name) |
| expected_template_arguments.update({'repo_id': 'hadoop'}) |
| |
| self.assertEqual(expected_template_arguments, template_item.context._dict) |
| self.assertEqual(RHEL_SUSE_DEFAULT_TEMPLATE, template) |
| |
| |
| @patch.object(OSCheck, "is_suse_family") |
| @patch.object(OSCheck, "is_ubuntu_family") |
| @patch.object(OSCheck, "is_redhat_family") |
| @patch.object(System, "os_family", new='suse') |
| @patch("resource_management.libraries.providers.repository.File") |
| @patch("resource_management.libraries.providers.repository.checked_call") |
| @patch("resource_management.core.sudo.read_file") |
| @patch("os.path.isfile", new=MagicMock(return_value=True)) |
| def test_recreate_repo_suse(self, read_file_mock, checked_call_mock, file_mock, |
| is_redhat_family, is_ubuntu_family, is_suse_family): |
| is_redhat_family.return_value = False |
| is_ubuntu_family.return_value = False |
| is_suse_family.return_value = True |
| read_file_mock.return_value = "Dummy repo file contents" |
| checked_call_mock.return_value = 0, "Flushing zypper cache" |
| with Environment('/') as env: |
| with patch.object(repository, "__file__", new='/ambari/test/repo/dummy/path/file'): |
| # Check that zypper cache is flushed |
| Repository('hadoop', |
| base_url='http://download.base_url.org/rpm/', |
| mirror_list='https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| repo_template = RHEL_SUSE_DEFAULT_TEMPLATE, |
| repo_file_name='Repository') |
| |
| self.assertTrue(checked_call_mock.called) |
| |
| expected_repo_file_content = "[hadoop]\nname=hadoop\nmirrorlist=https://mirrors.base_url.org/?repo=Repository&arch=$basearch\n\npath=/\nenabled=1\ngpgcheck=0" |
| template = file_mock.call_args[1]['content'] |
| self.assertEqual(expected_repo_file_content, template) |
| |
| # Check that if content is equal, zypper cache is not flushed |
| checked_call_mock.reset_mock() |
| read_file_mock.return_value = expected_repo_file_content |
| |
| Repository('hadoop', |
| base_url='http://download.base_url.org/rpm/', |
| mirror_list='https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| repo_template = RHEL_SUSE_DEFAULT_TEMPLATE, |
| repo_file_name='Repository') |
| |
| self.assertFalse(checked_call_mock.called) |
| |
| expected_repo_file_content = "[hadoop]\nname=hadoop\nmirrorlist=https://mirrors.base_url.org/?repo=Repository&arch=$basearch\n\npath=/\nenabled=1\ngpgcheck=0" |
| template = file_mock.call_args[1]['content'] |
| self.assertEqual(expected_repo_file_content, template) |
| |
| |
| @patch.object(OSCheck, "is_suse_family") |
| @patch.object(OSCheck, "is_ubuntu_family") |
| @patch.object(OSCheck, "is_redhat_family") |
| @patch("resource_management.libraries.providers.repository.checked_call") |
| @patch.object(tempfile, "NamedTemporaryFile") |
| @patch("resource_management.libraries.providers.repository.Execute") |
| @patch("resource_management.libraries.providers.repository.File") |
| @patch("os.path.isfile", new=MagicMock(return_value=True)) |
| @patch("filecmp.cmp", new=MagicMock(return_value=False)) |
| @patch.object(System, "os_release_name", new='precise') |
| @patch.object(System, "os_family", new='ubuntu') |
| def test_create_repo_ubuntu_repo_exists(self, file_mock, execute_mock, |
| tempfile_mock, checked_call_mock, is_redhat_family, is_ubuntu_family, is_suse_family): |
| is_redhat_family.return_value = False |
| is_ubuntu_family.return_value = True |
| is_suse_family.return_value = False |
| tempfile_mock.return_value = MagicMock(spec=file) |
| tempfile_mock.return_value.__enter__.return_value.name = "/tmp/1.txt" |
| checked_call_mock.return_value = 0, "The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 123ABCD" |
| |
| with Environment('/') as env: |
| with patch.object(repository, "__file__", new='/ambari/test/repo/dummy/path/file'): |
| Repository('HDP', |
| base_url='http://download.base_url.org/rpm/', |
| repo_file_name='HDP', |
| repo_template = DEBIAN_DEFAUTL_TEMPLATE, |
| components = ['a','b','c'] |
| ) |
| |
| call_content = file_mock.call_args_list[0] |
| template_name = call_content[0][0] |
| template_content = call_content[1]['content'] |
| |
| self.assertEquals(template_name, '/tmp/1.txt') |
| self.assertEquals(template_content, 'deb http://download.base_url.org/rpm/ a b c') |
| |
| copy_item0 = str(file_mock.call_args_list[1]) |
| copy_item1 = str(file_mock.call_args_list[2]) |
| self.assertEqual(copy_item0, "call('/tmp/1.txt', content=StaticFile('/etc/apt/sources.list.d/HDP.list'))") |
| self.assertEqual(copy_item1, "call('/etc/apt/sources.list.d/HDP.list', content=StaticFile('/tmp/1.txt'))") |
| #'apt-get update -qq -o Dir::Etc::sourcelist="sources.list.d/HDP.list" -o APT::Get::List-Cleanup="0"') |
| execute_command_item = execute_mock.call_args_list[0][0][0] |
| |
| self.assertEqual(checked_call_mock.call_args_list[0][0][0], ['apt-get', 'update', '-qq', '-o', 'Dir::Etc::sourcelist=sources.list.d/HDP.list', '-o', 'Dir::Etc::sourceparts=-', '-o', 'APT::Get::List-Cleanup=0']) |
| self.assertEqual(execute_command_item, ('apt-key', 'adv', '--recv-keys', '--keyserver', 'keyserver.ubuntu.com', '123ABCD')) |
| |
| @patch("resource_management.libraries.providers.repository.checked_call") |
| @patch.object(tempfile, "NamedTemporaryFile") |
| @patch("resource_management.libraries.providers.repository.Execute") |
| @patch("resource_management.libraries.providers.repository.File") |
| @patch("os.path.isfile", new=MagicMock(return_value=True)) |
| @patch("filecmp.cmp", new=MagicMock(return_value=False)) |
| @patch.object(System, "os_release_name", new='precise') |
| @patch.object(System, "os_family", new='ubuntu') |
| def test_create_repo_ubuntu_gpg_key_wrong_output(self, file_mock, execute_mock, |
| tempfile_mock, checked_call_mock): |
| """ |
| Checks that GPG key is extracted from output without \r sign |
| """ |
| tempfile_mock.return_value = MagicMock(spec=file) |
| tempfile_mock.return_value.__enter__.return_value.name = "/tmp/1.txt" |
| checked_call_mock.return_value = 0, "The following signatures couldn't be verified because the public key is not available: NO_PUBKEY 123ABCD\r\n" |
| |
| with Environment('/') as env: |
| with patch.object(repository, "__file__", new='/ambari/test/repo/dummy/path/file'): |
| Repository('HDP', |
| base_url='http://download.base_url.org/rpm/', |
| repo_file_name='HDP', |
| repo_template = DEBIAN_DEFAUTL_TEMPLATE, |
| components = ['a','b','c'] |
| ) |
| |
| call_content = file_mock.call_args_list[0] |
| template_name = call_content[0][0] |
| template_content = call_content[1]['content'] |
| |
| self.assertEquals(template_name, '/tmp/1.txt') |
| self.assertEquals(template_content, 'deb http://download.base_url.org/rpm/ a b c') |
| |
| copy_item0 = str(file_mock.call_args_list[1]) |
| copy_item1 = str(file_mock.call_args_list[2]) |
| self.assertEqual(copy_item0, "call('/tmp/1.txt', content=StaticFile('/etc/apt/sources.list.d/HDP.list'))") |
| self.assertEqual(copy_item1, "call('/etc/apt/sources.list.d/HDP.list', content=StaticFile('/tmp/1.txt'))") |
| execute_command_item = execute_mock.call_args_list[0][0][0] |
| |
| self.assertEqual(checked_call_mock.call_args_list[0][0][0], ['apt-get', 'update', '-qq', '-o', 'Dir::Etc::sourcelist=sources.list.d/HDP.list', '-o', 'Dir::Etc::sourceparts=-', '-o', 'APT::Get::List-Cleanup=0']) |
| self.assertEqual(execute_command_item, ('apt-key', 'adv', '--recv-keys', '--keyserver', 'keyserver.ubuntu.com', '123ABCD')) |
| |
| @patch.object(tempfile, "NamedTemporaryFile") |
| @patch("resource_management.libraries.providers.repository.Execute") |
| @patch("resource_management.libraries.providers.repository.File") |
| @patch("os.path.isfile", new=MagicMock(return_value=True)) |
| @patch("filecmp.cmp", new=MagicMock(return_value=True)) |
| @patch.object(System, "os_release_name", new='precise') |
| @patch.object(System, "os_family", new='ubuntu') |
| def test_create_repo_ubuntu_doesnt_repo_exist(self, file_mock, execute_mock, tempfile_mock): |
| tempfile_mock.return_value = MagicMock(spec=file) |
| tempfile_mock.return_value.__enter__.return_value.name = "/tmp/1.txt" |
| |
| with Environment('/') as env: |
| with patch.object(repository, "__file__", new='/ambari/test/repo/dummy/path/file'): |
| Repository('HDP', |
| base_url='http://download.base_url.org/rpm/', |
| repo_file_name='HDP', |
| repo_template = DEBIAN_DEFAUTL_TEMPLATE, |
| components = ['a','b','c'] |
| ) |
| |
| call_content = file_mock.call_args_list[0] |
| template_name = call_content[0][0] |
| template_content = call_content[1]['content'] |
| |
| self.assertEquals(template_name, '/tmp/1.txt') |
| self.assertEquals(template_content, 'deb http://download.base_url.org/rpm/ a b c') |
| |
| self.assertEqual(file_mock.call_count, 2) |
| self.assertEqual(execute_mock.call_count, 0) |
| |
| |
| @patch("os.path.isfile", new=MagicMock(return_value=True)) |
| @patch.object(System, "os_family", new='ubuntu') |
| @patch("resource_management.libraries.providers.repository.Execute") |
| @patch("resource_management.libraries.providers.repository.File") |
| def test_remove_repo_ubuntu_repo_exist(self, file_mock, execute_mock): |
| with Environment('/') as env: |
| Repository('HDP', |
| action = "remove", |
| repo_file_name='HDP' |
| ) |
| |
| self.assertEqual(str(file_mock.call_args), "call('/etc/apt/sources.list.d/HDP.list', action='delete')") |
| self.assertEqual(execute_mock.call_args[0][0], ['apt-get', 'update', '-qq', '-o', 'Dir::Etc::sourcelist=sources.list.d/HDP.list', '-o', 'Dir::Etc::sourceparts=-', '-o', 'APT::Get::List-Cleanup=0']) |
| |
| @patch("os.path.isfile", new=MagicMock(return_value=False)) |
| @patch.object(System, "os_family", new='ubuntu') |
| @patch("resource_management.libraries.providers.repository.Execute") |
| @patch("resource_management.libraries.providers.repository.File") |
| def test_remove_repo_ubuntu_repo_doenst_exist(self, file_mock, execute_mock): |
| with Environment('/') as env: |
| Repository('HDP', |
| action = "remove", |
| repo_file_name='HDP' |
| ) |
| |
| self.assertEqual(file_mock.call_count, 0) |
| self.assertEqual(execute_mock.call_count, 0) |
| |
| @patch.object(OSCheck, "is_suse_family") |
| @patch.object(OSCheck, "is_ubuntu_family") |
| @patch.object(OSCheck, "is_redhat_family") |
| @patch.object(System, "os_family", new='redhat') |
| @patch("resource_management.libraries.providers.repository.File") |
| def test_remove_repo_redhat(self, file_mock, |
| is_redhat_family, is_ubuntu_family, is_suse_family): |
| is_redhat_family.return_value = True |
| is_ubuntu_family.return_value = False |
| is_suse_family.return_value = False |
| with Environment('/') as env: |
| Repository('hadoop', |
| action='remove', |
| base_url='http://download.base_url.org/rpm/', |
| mirror_list='https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| repo_file_name='Repository') |
| |
| self.assertTrue('hadoop' in env.resources['Repository']) |
| defined_arguments = env.resources['Repository']['hadoop'].arguments |
| expected_arguments = {'action': ['remove'], |
| 'base_url': 'http://download.base_url.org/rpm/', |
| 'mirror_list': 'https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| 'repo_file_name': 'Repository'} |
| self.assertEqual(defined_arguments, expected_arguments) |
| |
| |
| @patch.object(OSCheck, "is_suse_family") |
| @patch.object(OSCheck, "is_ubuntu_family") |
| @patch.object(OSCheck, "is_redhat_family") |
| @patch.object(System, "os_family", new='suse') |
| @patch("resource_management.libraries.providers.repository.File") |
| def test_remove_repo_suse(self, file_mock, |
| is_redhat_family, is_ubuntu_family, is_suse_family): |
| is_redhat_family.return_value = False |
| is_ubuntu_family.return_value = False |
| is_suse_family.return_value = True |
| with Environment('/') as env: |
| Repository('hadoop', |
| action='remove', |
| base_url='http://download.base_url.org/rpm/', |
| mirror_list='https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| repo_file_name='Repository') |
| |
| self.assertTrue('hadoop' in env.resources['Repository']) |
| defined_arguments = env.resources['Repository']['hadoop'].arguments |
| expected_arguments = {'action': ['remove'], |
| 'base_url': 'http://download.base_url.org/rpm/', |
| 'mirror_list': 'https://mirrors.base_url.org/?repo=Repository&arch=$basearch', |
| 'repo_file_name': 'Repository'} |
| self.assertEqual(defined_arguments, expected_arguments) |
| self.assertEqual(file_mock.call_args[1]['action'], 'delete') |
| self.assertEqual(file_mock.call_args[0][0], '/etc/zypp/repos.d/Repository.repo') |