def test_can_copy_directory(self, mock_close, mock_add): class DummyGuest(Guest): name = 'dummy' guest = DummyGuest(FakeContainer()) guest.lxd_container.files.put.return_value = True with tempfile.TemporaryDirectory() as d: os.mkdir('{}/d1'.format(d)) os.mkdir('{}/d1/d2'.format(d)) with open('{}/d1/f1'.format(d), 'wb') as f1: f1.write(b'dummy f1') with open('{}/d1/d2/f2'.format(d), 'wb') as f2: f2.write(b'dummy f2') with open('{}/f3'.format(d), 'wb') as f3: f3.write(b'dummy f3') guest.copy_directory(pathlib.Path(d), pathlib.PurePosixPath('/a/b/c')) assert mock_add.call_count == 1 assert mock_add.call_args[0][0] == str(pathlib.Path(d)) assert mock_add.call_args[1]['arcname'] == '.' assert mock_close.call_count == 1 assert guest.lxd_container.execute.call_count == 4 assert guest.lxd_container.execute.call_args_list[0][0] == (['mkdir', '-p', '/a/b/c'], ) assert guest.lxd_container.execute.call_args_list[1][0] == ([ 'mkdir', '-p', str(pathlib.PurePosixPath(guest._guest_temporary_tar_path).parent)], ) assert guest.lxd_container.execute.call_args_list[2][0] == ([ 'tar', '-xf', guest._guest_temporary_tar_path, '-C', '/a/b/c'], ) assert guest.lxd_container.execute.call_args_list[3][0] == ([ 'rm', '-f', guest._guest_temporary_tar_path], ) assert guest.lxd_container.files.put.call_count == 1 assert guest.lxd_container.files.put.call_args[0][0] == guest._guest_temporary_tar_path
def test_trigger_packages_installation_on_the_guest_if_the_related_attr_is_defined( self): class DummyProvisioner(Provisioner): name = 'myprovisioner' schema = { 'test': 'test', } guest_required_packages_debian = [ 'test01', 'test02', ] container = FakeContainer() lxd_container = container._container lxd_container.execute.return_value = ('ok', 'ok', '') host = unittest.mock.Mock() guest = DebianGuest(container) provisioner = DummyProvisioner('./', host, [guest], {}) provisioner.setup() assert lxd_container.execute.call_count == 2 assert lxd_container.execute.call_args_list[0][0] == \ (['apt-get', 'update'], ) assert lxd_container.execute.call_args_list[1][0] == \ (['apt-get', 'install', '-y', 'test01', 'test02', ], )
def test_can_install_packages(self): guest = AlpineGuest(FakeContainer()) guest.install_packages(['python', 'openssh', ]) assert guest.lxd_container.execute.call_count == 2 assert guest.lxd_container.execute.call_args_list[0][0] == (['apk', 'update'], ) assert guest.lxd_container.execute.call_args_list[1][0] == \ (['apk', 'add', 'python', 'openssh'], )
def test_can_create_a_user_with_a_custom_home_directory(self): class DummyGuest(Guest): name = 'dummy' guest = DummyGuest(FakeContainer()) guest.create_user('usertest', home='/opt/usertest') assert guest.lxd_container.execute.call_count == 1 assert guest.lxd_container.execute.call_args[0] == \ (['useradd', '--create-home', '--home-dir', '/opt/usertest', 'usertest'], )
def test_inventory_with_lxd_transport(self): c = FakeContainer(name='c1') provisioner = AnsibleProvisioner('./', Host(), [DebianGuest(c)], { 'playbook': 'deploy.yml', 'lxd_transport': True }) inv = provisioner.get_inventory() assert 'ansible_host={}'.format(c.lxd_name) in inv
def test_can_install_packages(self): guest = ArchLinuxGuest(FakeContainer()) guest.install_packages([ 'python', 'openssh', ]) assert guest.lxd_container.execute.call_count == 1 assert guest.lxd_container.execute.call_args[0] == \ (['pacman', '-S', '--noconfirm', 'python', 'openssh'], )
def test_can_install_packages(self): guest = FedoraGuest(FakeContainer()) guest.install_packages([ 'python', 'openssh', ]) assert guest.lxd_container.execute.call_count == 1 assert guest.lxd_container.execute.call_args[0] == \ (['dnf', '-y', 'install', 'python', 'openssh', ], )
def test_can_install_packages(self): guest = OpenSUSEGuest(FakeContainer()) guest.install_packages([ 'python', 'openssh', ]) assert guest.lxd_container.execute.call_count == 1 assert guest.lxd_container.execute.call_args[0] == \ (['zypper', '--non-interactive', 'install', 'python', 'openssh', ], )
def test_can_create_a_user_with_a_custom_shell(self): class DummyGuest(Guest): name = 'dummy' guest = DummyGuest(FakeContainer()) shell = "/bin/zsh" guest.create_user('usertest', shell=shell) assert guest.lxd_container.execute.call_count == 1 assert guest.lxd_container.execute.call_args[0] == \ (['useradd', '--create-home', '-s', shell, 'usertest'], )
def test_uidgid(self): class DummyGuest(Guest): name = 'dummy' guest = DummyGuest(FakeContainer()) guest.lxd_container.execute.return_value = (0, "10000", "") uid, gid = guest.uidgid("user") assert uid == 10000 assert gid == 10000
def test_can_add_ssh_pubkey_to_root_authorized_keys(self): class DummyGuest(Guest): name = 'dummy' guest = DummyGuest(FakeContainer()) guest.add_ssh_pubkey_to_authorized_keys('pubkey', '/root') assert guest.lxd_container.execute.call_count == 1 assert guest.lxd_container.execute.call_args[0] == (['mkdir', '-p', '/root/.ssh'], ) assert guest.lxd_container.files.put.call_count == 1 assert guest.lxd_container.files.put.call_args[0] == \ ('/root/.ssh/authorized_keys', 'pubkey', )
def test_can_create_a_user_with_a_custom_password(self): class DummyGuest(Guest): name = 'dummy' password = '******' \ '39mJQrJcZ5vIKJVIfwsKOZajhbPw0.Zqd0jU2NDLAnp9J/1' guest = DummyGuest(FakeContainer()) guest.create_user('usertest', password=password) assert guest.lxd_container.execute.call_count == 1 assert guest.lxd_container.execute.call_args[0] == \ (['useradd', '--create-home', '-p', password, 'usertest'], )
def test_can_give_mapped_user_access_to_share(self, mocked_stat, mocked_call): class MockedContainer(object): name = 'test' mocked_stat.return_value = unittest.mock.MagicMock(st_uid='19958953') host = Host() host.give_mapped_user_access_to_share(FakeContainer(), '.', '.') assert mocked_call.call_count == 1 assert mocked_call.call_args[0] == ( 'setfacl -Rm user:lxd:rwx,default:user:lxd:rwx,user:19958953:rwx,default:user:19958953' ':rwx .',)
def test_can_install_packages(self): guest = DebianGuest(FakeContainer()) guest.install_packages([ 'python', 'openssh', ]) assert guest.lxd_container.execute.call_count == 2 assert guest.lxd_container.execute.call_args_list[0][0] == \ (['apt-get', 'update', ], ) assert guest.lxd_container.execute.call_args_list[1][0] == \ (['apt-get', 'install', '-y', 'python', 'openssh', ], )
def test_setup_users_adds_ssh_pubkey_to_authorized_keys(self): class DummyGuest(Guest): name = 'dummy' container = FakeContainer() container._setup_users() guest = DummyGuest(container) assert guest.lxd_container.execute.call_count == 1 assert guest.lxd_container.execute.call_args[0] == (['mkdir', '-p', '/root/.ssh'], ) assert guest.lxd_container.files.put.call_count == 1 assert guest.lxd_container.files.put.call_args[0][0] == \ '/root/.ssh/authorized_keys'
def test_can_run_commands_on_the_guest_side(self): container = FakeContainer() lxd_container = container._container host = Host() guest = DebianGuest(container) cmd = """touch f && echo "Here's the PATH" $PATH >> /tmp/test.txt""" provisioner = ShellProvisioner('./', host, [guest], {'inline': cmd}) provisioner.provision() assert lxd_container.execute.call_count == 1 assert lxd_container.execute.call_args_list[0][0] == ([ 'sh', '-c', cmd ], )
def test_inventory_contains_groups(self): c1 = FakeContainer(name='c1') c2 = FakeContainer(name='c2') # c3 is deliberately not part of our guests list. This is to test that it doesn't end up # in the inventory and result in spurious unreachable hosts. These situations can happen # in two ways: errors in the config file, or guest filtering in the command line ("lxdock # provision c1, c2" for example). provisioner = AnsibleProvisioner( './', Host(), [DebianGuest(c1), DebianGuest(c2)], { 'playbook': 'deploy.yml', 'groups': { 'g1': ['c1', 'c2'], 'g2': ['c1', 'c3'] } }) inv = provisioner.get_inventory() # group order is not guaranteed. our tests have to be written with that in mind. groups = re.findall(r'\[(g1|g2)\]([^[]+)', inv, re.MULTILINE) # we sort so that g1 will be first all the time groups = sorted([(gname, hosts.strip()) for gname, hosts in groups]) assert sorted(groups) == [('g1', 'c1\nc2'), ('g2', 'c1')]
def test_can_run_commands_on_the_host_side(self, mock_popen): host = Host() guest = DebianGuest(FakeContainer()) provisioner = ShellProvisioner( './', host, [guest], { 'inline': """touch f && echo "Here's the PATH" $PATH >> /tmp/test.txt""", 'side': 'host', }) provisioner.provision() assert mock_popen.call_args[0] == ( """sh -c 'touch f && echo "Here'"'"'s the PATH" $PATH >> /tmp/test.txt'""", )
def test_can_copy_file(self): class DummyGuest(Guest): name = 'dummy' guest = DummyGuest(FakeContainer()) guest.lxd_container.files.put.return_value = True with tempfile.NamedTemporaryFile() as f: f.write(b'dummy file') f.flush() guest.copy_file(pathlib.Path(f.name), pathlib.PurePath('/a/b/c')) assert guest.lxd_container.execute.call_count == 1 assert guest.lxd_container.execute.call_args[0] == (['mkdir', '-p', '/a/b'], ) assert guest.lxd_container.files.put.call_count == 1 assert guest.lxd_container.files.put.call_args[0] == ('/a/b/c', b'dummy file')
def test_can_run_a_script_on_the_guest_side(self, mock_open): container = FakeContainer() lxd_container = container._container host = Host() guest = DebianGuest(container) provisioner = ShellProvisioner('./', host, [guest], { 'script': 'test.sh', }) provisioner.provision() assert lxd_container.execute.call_count == 2 assert lxd_container.execute.call_args_list[0][0] == ([ 'chmod', '+x', '/tmp/test.sh', ], ) assert lxd_container.execute.call_args_list[1][0] == ([ '/tmp/test.sh', ], )
def test_should_not_reinstall_packages_if_already_installed(self): guest = GentooGuest(FakeContainer()) # Retcode 0: the package has been found locally guest.lxd_container.execute.return_value = (0, 'ok', '') guest.install_packages([ 'python', 'openssh', ]) assert guest.lxd_container.execute.call_count == 3 assert guest.lxd_container.execute.call_args_list[0][0] == \ (['emerge', 'app-portage/gentoolkit'], ) for i, p in enumerate([ 'python', 'openssh', ]): assert guest.lxd_container.execute.call_args_list[i + 1][0] == ([ 'equery', 'list', p ], )
def test_can_properly_setup_ssh_for_alpine_guests(self): container = FakeContainer() lxd_container = container._container lxd_container.execute.return_value = ('ok', 'ok', '') host = Host() guest = AlpineGuest(container) provisioner = AnsibleProvisioner('./', host, [guest], {'playbook': 'deploy.yml'}) provisioner.setup() EXPECTED = [ ['apk', 'update'], ['apk', 'add'] + AnsibleProvisioner.guest_required_packages_alpine, ['apk', 'update'], ['apk', 'add', 'openssh'], ['rc-update', 'add', 'sshd'], ['/etc/init.d/sshd', 'start'], ] calls = [tup[0][0] for tup in lxd_container.execute.call_args_list] assert calls == EXPECTED
def test_trigger_specific_setup_on_the_guest_if_the_related_method_is_defined( self): class DummyProvisioner(Provisioner): name = 'myprovisioner' schema = { 'test': 'test', } called = False def setup_guest_debian(self, guest): self.called = True container = FakeContainer() lxd_container = container._container lxd_container.execute.return_value = ('ok', 'ok', '') host = unittest.mock.Mock() guest = DebianGuest(container) provisioner = DummyProvisioner('./', host, [guest], {}) provisioner.setup() assert provisioner.called
def test_should_install_packages_if_not_installed(self): guest = GentooGuest(FakeContainer()) # Retcode 1: "No installed packages matching {keyword}" guest.lxd_container.execute.return_value = (1, 'ok', '') guest.install_packages([ 'python', 'openssh', ]) assert guest.lxd_container.execute.call_count == 5 assert guest.lxd_container.execute.call_args_list[0][0] == \ (['emerge', 'app-portage/gentoolkit'], ) for i, p in enumerate([ 'python', 'openssh', ]): assert guest.lxd_container.execute.call_args_list[2 * i + 1][0] == \ (['equery', 'list', p], ) assert guest.lxd_container.execute.call_args_list[2 * i + 2][0] == ([ 'emerge', p ], )
def test_can_run_ansible_playbooks(self, mock_popen, options, expected_cmdargs): host = Host() guest = DebianGuest(FakeContainer()) lxd_state = unittest.mock.Mock() lxd_state.network.__getitem__ = unittest.mock.MagicMock(return_value={ 'addresses': [ { 'family': 'init', 'address': '0.0.0.0', }, ] }) guest.lxd_container.state.return_value = lxd_state options['playbook'] = 'deploy.yml' provisioner = AnsibleProvisioner('./', host, [guest], options) provisioner.provision() m = re.match( r'ANSIBLE_HOST_KEY_CHECKING=False ansible-playbook --inventory-file /[/\w]+ ' r'(.*)\s?./deploy.yml', mock_popen.call_args[0][0]) assert m assert m.group(1).strip() == expected_cmdargs