def test_create_users(self): password = '******' \ '39mJQrJcZ5vIKJVIfwsKOZajhbPw0.Zqd0jU2NDLAnp9J/1' container_options = { 'name': self.containername('createusers'), 'image': 'ubuntu/xenial', 'users': [ { 'name': 'user01' }, { 'name': 'user02', 'home': '/opt/user02' }, { 'name': 'user03', 'password': password }, ], } container = Container('myproject', THIS_DIR, self.client, **container_options) guest_mock = unittest.mock.Mock() container._container_guest = guest_mock container.up() assert guest_mock.create_user.call_count == 3 assert guest_mock.create_user.call_args_list[0][0][0] == 'user01' assert guest_mock.create_user.call_args_list[1][0][0] == 'user02' assert guest_mock.create_user.call_args_list[2][0][0] == 'user03' assert guest_mock.create_user.call_args_list[1][1][ 'home'] == '/opt/user02' assert guest_mock.create_user.call_args_list[2][1][ 'password'] == password
def test_raises_an_error_if_profile_does_not_exist(self): container_options = { 'name': self.containername('newcontainer'), 'image': 'alpine/3.6', 'mode': 'pull', 'profiles': ['default', '39mJQrJcZ5vIKJVIfwsKOZajhbPw0']} container = Container('myproject', THIS_DIR, self.client, **container_options) with pytest.raises(ContainerOperationFailed): container.up()
def test_can_set_up_a_container_that_does_not_exist(self): container_options = { 'name': self.containername('newcontainer'), 'image': 'alpine/3.6', 'mode': 'pull', } container = Container('myproject', THIS_DIR, self.client, **container_options) container.up() assert container._container.status_code == constants.CONTAINER_RUNNING assert container._container.config['user.lxdock.made'] == '1' assert container._container.config['user.lxdock.homedir'] == THIS_DIR
def test_can_set_profiles(self): container_options = { 'name': self.containername('newcontainer'), 'image': 'alpine/3.6', 'mode': 'pull', 'profiles': ['default']} container = Container('myproject', THIS_DIR, self.client, **container_options) container.up() assert container._container.status_code == constants.CONTAINER_RUNNING assert container._container.profiles == ['default']
def test_can_return_its_status(self, persistent_container): unknown_container = Container('myproject', THIS_DIR, self.client, **{ 'name': self.containername('unknown'), 'image': 'alpine/3.6', 'mode': 'pull', }) assert unknown_container.status == 'not-created' persistent_container.halt() assert persistent_container.status == 'stopped' persistent_container.up() assert persistent_container.status == 'running'
def test_halting_a_container_doesnt_create_it(self): container_options = { 'name': self.containername('doesnotexist'), 'image': 'alpine/3.10', } container = Container('myproject', THIS_DIR, self.client, **container_options) container.halt() assert not container.exists
def test_can_tell_if_a_container_exists_or_not(self, persistent_container): unkonwn_container = Container( 'myproject', THIS_DIR, self.client, **{ 'name': self.containername('unkonwn'), 'image': 'ubuntu/xenial', 'mode': 'pull', }) assert persistent_container.exists assert not unkonwn_container.exists
def test_can_destroy_a_container_and_run_this_action_for_a_container_that_does_not_exist(self): container_options = { 'name': self.containername('doesnotexist'), 'image': 'alpine/3.6', 'mode': 'pull', } container = Container('myproject', THIS_DIR, self.client, **container_options) container.destroy() assert not container.exists container.up() assert container.exists container.destroy() assert not container.exists
def test_create_users(self): password = '******' \ '39mJQrJcZ5vIKJVIfwsKOZajhbPw0.Zqd0jU2NDLAnp9J/1' container_options = { 'name': self.containername('createusers'), 'image': 'alpine/3.10', 'users': [ { 'name': 'user01' }, { 'name': 'user02', 'home': '/opt/user02' }, { 'name': 'user03', 'password': password }, ], } container = Container('myproject', THIS_DIR, self.client, **container_options) guest_mock = unittest.mock.Mock() mock_uids = { 'user01': (1000, 1000), 'user02': (1001, 1001), 'user03': (1002, 1002) } guest_mock.uidgid = unittest.mock.Mock() guest_mock.uidgid.side_effect = lambda name: mock_uids[name] container._container_guest = guest_mock host_mock = unittest.mock.Mock() host_mock.get_ssh_pubkey = unittest.mock.Mock(return_value='pubkey') container._container_host = host_mock container.up() # Check if all users have been created assert guest_mock.create_user.call_count == 3 assert guest_mock.create_user.call_args_list[0][0][0] == 'user01' assert guest_mock.create_user.call_args_list[1][0][0] == 'user02' assert guest_mock.create_user.call_args_list[2][0][0] == 'user03' assert guest_mock.create_user.call_args_list[1][1][ 'home'] == '/opt/user02' assert guest_mock.create_user.call_args_list[2][1][ 'password'] == password # Check if the SSH key has been deployed to all users guest_mock.add_ssh_pubkey_to_authorized_keys.assert_any_call( 'pubkey', '/root') guest_mock.add_ssh_pubkey_to_authorized_keys.assert_any_call( 'pubkey', '/home/user01', 1000, 1000) guest_mock.add_ssh_pubkey_to_authorized_keys.assert_any_call( 'pubkey', '/opt/user02', 1001, 1001) guest_mock.add_ssh_pubkey_to_authorized_keys.assert_any_call( 'pubkey', '/home/user03', 1002, 1002)
def test_can_set_shell_environment_variables(self, mocked_call): # Environment variables in the shell can be set through configuration. container_options = { 'name': self.containername('shell-env'), 'image': 'alpine/3.6', 'environment': {'FOO': 'bar', 'BAR': 42}, } container = Container('myproject', THIS_DIR, self.client, **container_options) container.up() container.shell() assert container._container.config['environment.FOO'] == 'bar' assert container._container.config['environment.BAR'] == '42'
def test_can_open_a_shell_for_a_specific_shelluser(self, mocked_call): container_options = { 'name': self.containername('shellspecificuser'), 'image': 'alpine/3.6', 'shell': {'user': '******'}, } container = Container('myproject', THIS_DIR, self.client, **container_options) container.up() container.shell() assert mocked_call.call_count == 1 assert mocked_call.call_args[0][0] == \ 'lxc exec {} -- su -l test'.format(container.lxd_name)
def test_can_destroy_all_the_containers_of_a_project(self): homedir = os.path.join(FIXTURE_ROOT, 'project03') container_options = { 'name': self.containername('dummytest'), 'image': 'alpine/3.6', } project = Project( 'project02', homedir, self.client, [Container('myproject', THIS_DIR, self.client, **container_options)], provisioning_steps=[]) project.up() project.destroy() for container in project.containers: assert not container.exists
def test_can_provision_a_container_shell_inline(self): container_options = { 'name': self.containername('willprovision'), 'image': 'alpine/3.6', 'mode': 'pull', 'environment': {'PATH': '/dummy_test:/bin:/usr/bin:/usr/local/bin'}, 'provisioning': [ {'type': 'shell', 'inline': """touch f && echo "Here's the PATH" $PATH >> /tmp/test.txt""", } ], } container = Container('myproject', THIS_DIR, self.client, **container_options) container.up() container.provision() assert container._container.files.get('/tmp/test.txt').strip() == ( b"Here's the PATH /dummy_test:/bin:/usr/bin:/usr/local/bin")
def test_can_run_shell_command_for_a_specific_shelluser(self, mocked_call): container_options = { 'name': self.containername('shellspecificuser'), 'image': 'alpine/3.6', 'shell': {'user': '******'}, } container = Container('myproject', THIS_DIR, self.client, **container_options) container.up() container.shell(command='cd /; ls -l') assert mocked_call.call_count == 1 assert mocked_call.call_args[0][0] == \ 'lxc exec {} -- su -l test -s {}'.format( container.lxd_name, container._guest_shell_script_file) script = container._container.files.get(container._guest_shell_script_file) assert script == b"""#!/bin/sh\ncd /; ls -l\n"""
def test_can_run_quoted_shell_command_for_a_specific_shelluser(self, mocked_call): container_options = { 'name': self.containername('shellspecificuser'), 'image': 'alpine/3.6', 'shell': {'user': '******', 'home': '/opt', }, } container = Container('myproject', THIS_DIR, self.client, **container_options) container.up() container.shell(cmd_args=['echo', 'he re"s', '-u', '$PATH']) assert mocked_call.call_count == 1 assert mocked_call.call_args[0][0] == \ 'lxc exec {} --env HOME=/opt -- su -m test -s {}'.format( container.lxd_name, container._guest_shell_script_file) script = container._container.files.get(container._guest_shell_script_file) assert script == b"""#!/bin/sh\necho 'he re"s' -u '$PATH'\n"""
def test_can_provision_all_the_containers_of_a_project(self): homedir = os.path.join(FIXTURE_ROOT, 'project03') container_options = { 'name': self.containername('dummytest'), 'image': 'alpine/3.6', 'mode': 'pull', } provisioning_steps = [ {'type': 'ansible', 'playbook': os.path.join(THIS_DIR, 'fixtures/provision_with_ansible.yml'), } ] project = Project( 'project02', homedir, self.client, [Container('myproject', THIS_DIR, self.client, **container_options)], provisioning_steps=provisioning_steps) project.up() # implicit provisioning for container in project.containers: assert container.is_provisioned
def test_can_destroy_all_the_containers_of_a_project(self): homedir = os.path.join(FIXTURE_ROOT, 'project03') container_options = { 'name': self.containername('dummytest'), 'image': 'ubuntu/xenial', 'mode': 'pull', 'provisioning': [ {'type': 'ansible', 'playbook': os.path.join(THIS_DIR, 'fixtures/provision_with_ansible.yml'), } ], } project = Project( 'project02', homedir, self.client, [Container('myproject', THIS_DIR, self.client, **container_options)]) project.up() project.destroy() for container in project.containers: assert not container.exists
def test_can_provision_some_specific_containers_of_a_project(self): homedir = os.path.join(FIXTURE_ROOT, 'project03') container_options = { 'name': self.containername('thisisatest'), 'image': 'ubuntu/xenial', 'mode': 'pull', 'provisioning': [ {'type': 'ansible', 'playbook': os.path.join(THIS_DIR, 'fixtures/provision_with_ansible.yml'), } ], } project = Project( 'project02', homedir, self.client, [Container('myproject', THIS_DIR, self.client, **container_options)]) project.up() project.provision(container_names=['lxdock-pytest-thisisatest']) container_web = project.get_container_by_name('lxdock-pytest-thisisatest') assert container_web.is_provisioned
def test_must_be_created_and_running_decorator_works(persistent_container): @must_be_created_and_running def dummy_action(self): return 42 persistent_container.dummy_action = types.MethodType(dummy_action, persistent_container) persistent_container.halt() assert persistent_container.dummy_action() is None persistent_container.up() assert persistent_container.dummy_action() == 42 del persistent_container.dummy_action non_created_container_options = { 'name': 'lxdock-nonexistingcontainer', 'image': 'alpine/3.6', 'mode': 'pull', } non_created_container = Container( 'myproject', THIS_DIR, persistent_container.client, **non_created_container_options) non_created_container.dummy_action = types.MethodType(dummy_action, non_created_container) assert non_created_container.dummy_action() is None
def test_can_open_a_shell_for_a_specific_shelluser(self, mocked_call): container_options = { 'name': self.containername('dummy'), 'image': 'ubuntu/xenial', 'mode': 'pull', 'shell': { 'user': '******', 'home': '/opt', }, } container = Container('myproject', THIS_DIR, self.client, **container_options) container.up() container.shell() assert mocked_call.call_count == 1 assert mocked_call.call_args[0][0] == \ 'lxc exec {} --env HOME=/opt -- su -m test'.format(container.lxd_name)
def test_get_container_lxc_config(self): """Test that _get_container generates a valid lxc_config """ # The options below has an lxc_config value, that overrides some values # that are driven within lxdoc, these values are marked as invalid and should not # be passed directly to the container at creation time. container_options = { 'name': self.containername('lxc-config'), 'image': 'alpine/3.10', 'lxc_config': { 'security.privileged': 'invalid', 'user.lxdock.homedir': 'invalid', 'user.lxdock.made': 'invalid', 'valid_key': 'valid_value', }, } cont_return = () # mock container object to return def mock_create(container_config, *args, **kwargs): """Mocks the container create call, returns the mock container object and also ensures that the container_config is correct """ config = container_config['config'] # Values below should not be driven by the values in container_options assert config['security.privileged'] != 'invalid' assert config['user.lxdock.homedir'] != 'invalid' assert config['user.lxdock.made'] != 'invalid' # Value below is a custom value that should be passed from container_options assert config['valid_key'] == 'valid_value' return cont_return client_mock = unittest.mock.Mock( **{ 'containers.create.side_effect': mock_create, 'containers.get.side_effect': NotFound(''), }) container = Container('myproject', THIS_DIR, client_mock, **container_options) assert container._get_container() is cont_return assert client_mock.containers.get.called assert client_mock.containers.create.called
def test_can_provision_a_container(self): container_options = { 'name': self.containername('dummy'), 'image': 'ubuntu/xenial', 'mode': 'pull', 'provisioning': [{ 'type': 'ansible', 'playbook': os.path.join(THIS_DIR, 'fixtures/provision_with_ansible.yml'), }], } container = Container('myproject', THIS_DIR, self.client, **container_options) container.up() assert container._container.config['user.lxdock.provisioned'] == 'true' assert container._container.files.get( '/dummytest').strip() == b'dummytest'