def setUp(self): super().setUp() self.config_data = { 'architectures': ['amd64'], 'name': 'my-package', 'version': '1.0', 'description': 'my description', 'summary': 'my summary', 'confinement': 'devmode', 'environment': { 'GLOBAL': 'y', }, 'parts': { 'test-part': { 'plugin': 'nil', } } } patcher = patch('snapcraft.internal.project_loader.get_snapcraft_yaml') self.mock_get_yaml = patcher.start() self.mock_get_yaml.return_value = os.path.join('snap', 'snapcraft.yaml') self.addCleanup(patcher.stop) # Ensure the ensure snapcraft.yaml method has something to copy. _create_file(os.path.join('snap', 'snapcraft.yaml')) self.meta_dir = os.path.join(self.prime_dir, 'meta') self.hooks_dir = os.path.join(self.meta_dir, 'hooks') self.snap_yaml = os.path.join(self.meta_dir, 'snap.yaml') self.project_options = ProjectOptions()
def setUp(self): super().setUp() # TODO move to use outer interface self.packager = _snap_packaging._SnapPackaging( {'confinement': 'devmode'}, ProjectOptions(), 'dummy') self.packager._is_host_compatible_with_base = True
def test_cleanbuild(self, mock_pet): fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(fake_logger) mock_pet.return_value = 'my-pet' project_options = ProjectOptions() lxd.Cleanbuilder('snap.snap', 'project.tar', project_options).execute() expected_arch = project_options.deb_arch self.assertEqual( 'Setting up container with project assets\n' 'Copying snapcraft cache into container\n' 'Waiting for a network connection...\n' 'Network connection established\n' 'Retrieved snap.snap\n', fake_logger.output) self.check_call_mock.assert_has_calls([ call([ 'lxc', 'launch', '-e', 'ubuntu:xenial/{}'.format(expected_arch), 'local:snapcraft-my-pet' ]), call([ 'lxc', 'config', 'set', 'local:snapcraft-my-pet', 'environment.SNAPCRAFT_SETUP_CORE', '1' ]), call([ 'lxc', 'file', 'push', 'project.tar', 'local:snapcraft-my-pet//root/project.tar' ]), call([ 'lxc', 'exec', 'local:snapcraft-my-pet', '--', 'tar', 'xvf', '/root/project.tar' ]), call([ 'lxc', 'exec', 'local:snapcraft-my-pet', '--', 'python3', '-c', 'import urllib.request; ' 'urllib.request.urlopen(' '"http://start.ubuntu.com/connectivity-check.html", ' 'timeout=5)' ]), call([ 'lxc', 'exec', 'local:snapcraft-my-pet', '--', 'apt-get', 'update' ]), call([ 'lxc', 'exec', 'local:snapcraft-my-pet', '--', 'apt-get', 'install', 'snapcraft', '-y' ]), call([ 'lxc', 'exec', 'local:snapcraft-my-pet', '--', 'snapcraft', 'snap', '--output', 'snap.snap' ]), call([ 'lxc', 'file', 'pull', 'local:snapcraft-my-pet//root/snap.snap', 'snap.snap' ]), call(['lxc', 'stop', '-f', 'local:snapcraft-my-pet']), ])
def test_user_agent_darwin(self): arch = ProjectOptions().deb_arch expected = f"snapcraft/{snapcraft_version} Darwin ({arch})" self.expectThat( storeapi._agent.get_user_agent(platform="darwin"), Equals(expected) )
def test_user_agent_linux_unknown(self): self.useFixture(FakeOsRelease(name=None, version_id=None)) arch = ProjectOptions().deb_arch expected = f"snapcraft/{snapcraft_version} Unknown/Unknown Version ({arch})" self.expectThat(storeapi._agent.get_user_agent("linux"), Equals(expected))
def test_cleanbuild_with_remote(self, mock_pet): mock_pet.return_value = 'my-pet' project_options = ProjectOptions() lxd.Cleanbuilder('snap.snap', 'project.tar', project_options, remote='my-remote').execute() expected_arch = project_options.deb_arch self.check_call_mock.assert_has_calls([ call(['lxc', 'launch', '-e', 'ubuntu:xenial/{}'.format(expected_arch), 'my-remote:snapcraft-my-pet']), call(['lxc', 'config', 'set', 'my-remote:snapcraft-my-pet', 'environment.SNAPCRAFT_SETUP_CORE', '1']), call(['lxc', 'file', 'push', 'project.tar', 'my-remote:snapcraft-my-pet//root/project.tar']), call(['lxc', 'exec', 'my-remote:snapcraft-my-pet', '--', 'tar', 'xvf', '/root/project.tar']), call(['lxc', 'exec', 'my-remote:snapcraft-my-pet', '--', 'python3', '-c', 'import urllib.request; ' 'urllib.request.urlopen(' '"http://start.ubuntu.com/connectivity-check.html", ' 'timeout=5)']), call(['lxc', 'exec', 'my-remote:snapcraft-my-pet', '--', 'apt-get', 'update']), call(['lxc', 'exec', 'my-remote:snapcraft-my-pet', '--', 'apt-get', 'install', 'snapcraft', '-y']), call(['lxc', 'exec', 'my-remote:snapcraft-my-pet', '--', 'snapcraft', 'snap', '--output', 'snap.snap']), call(['lxc', 'file', 'pull', 'my-remote:snapcraft-my-pet//root/snap.snap', 'snap.snap']), call(['lxc', 'stop', '-f', 'my-remote:snapcraft-my-pet']), ])
def test_user_agent_linux(self): self.useFixture(FakeOsRelease()) arch = ProjectOptions().deb_arch expected = f"snapcraft/{snapcraft_version} Ubuntu/16.04 ({arch})" self.expectThat(storeapi._agent.get_user_agent("linux"), Equals(expected))
def test_output_set_correctly(self): project = ProjectOptions() instance = lxd.Containerbuild(project_options=project, source='tarball.tgz', metadata=self.snap, container_name='name') self.assertThat(instance._snap_output, Equals(self.expected))
def setUp(self): super().setUp() self.fake_lxd = tests.fixture_setup.FakeLXD() self.useFixture(self.fake_lxd) self.fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(self.fake_logger) self.project_options = ProjectOptions(target_deb_arch=self.target_arch)
def setUp(self): super().setUp() self.fake_elf = fixture_setup.FakeElf(root_path=self.path) self.useFixture(self.fake_elf) self.content_dirs = [] self.arch_triplet = ProjectOptions().arch_triplet
def get_project_options(**kwargs): project_args = dict( use_geoip=kwargs.pop('enable_geoip'), parallel_builds=not kwargs.pop('no_parallel_builds'), target_deb_arch=kwargs.pop('target_arch'), ) return ProjectOptions(**project_args)
def test_cleanbuild(self, mock_pet): fake_lxd = tests.fixture_setup.FakeLXD() self.useFixture(fake_lxd) fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(fake_logger) mock_pet.return_value = 'my-pet' project_options = ProjectOptions() metadata = {'name': 'project'} project_folder = 'build_project' lxd.Cleanbuilder(output='snap.snap', source='project.tar', metadata=metadata, remote=self.remote, project_options=project_options).execute() expected_arch = project_options.deb_arch self.assertEqual( 'Setting up container with project assets\n' 'Waiting for a network connection...\n' 'Network connection established\n' 'Retrieved snap.snap\n', fake_logger.output) container_name = '{}:snapcraft-my-pet'.format(self.remote) fake_lxd.check_call_mock.assert_has_calls([ call(['lxc', 'launch', '-e', 'ubuntu:xenial/{}'.format(expected_arch), container_name]), call(['lxc', 'config', 'set', container_name, 'environment.SNAPCRAFT_SETUP_CORE', '1']), call(['lxc', 'exec', container_name, '--env', 'HOME=/{}'.format(project_folder), '--', 'mkdir', project_folder]), call(['lxc', 'file', 'push', os.path.realpath('project.tar'), '{}/build_project/project.tar'.format(container_name)]), call(['lxc', 'exec', container_name, '--env', 'HOME=/{}'.format(project_folder), '--', 'tar', 'xvf', 'project.tar']), call(['lxc', 'exec', container_name, '--env', 'HOME=/{}'.format(project_folder), '--', 'python3', '-c', 'import urllib.request; ' 'urllib.request.urlopen(' '"http://start.ubuntu.com/connectivity-check.html", ' 'timeout=5)']), call(['lxc', 'exec', container_name, '--env', 'HOME=/{}'.format(project_folder), '--', 'apt-get', 'update']), call(['lxc', 'exec', container_name, '--env', 'HOME=/{}'.format(project_folder), '--', 'apt-get', 'install', 'snapcraft', '-y']), call(['lxc', 'exec', container_name, '--env', 'HOME=/{}'.format(project_folder), '--', 'snapcraft', 'snap', '--output', 'snap.snap']), call(['lxc', 'file', 'pull', '{}/{}/snap.snap'.format(container_name, project_folder), 'snap.snap']), call(['lxc', 'stop', '-f', container_name]), ])
def test_remote_does_not_exist(self, mock_sleep, mock_run): self.check_output_mock.side_effect = check_output_side_effect( fail_on_remote=True) project_options = ProjectOptions(debug=False) with ExpectedException(lxd.SnapcraftEnvironmentError, 'There are either.*my-remote.*'): lxd.Cleanbuilder('snap.snap', 'project.tar', project_options, remote='my-remote')
def setUp(self): super().setUp() # TODO move to use outer interface self.packager = _snap_packaging._SnapPackaging( {'confinement': 'devmode'}, ProjectOptions(), 'dummy' )
def test_download_from_branded_store_requires_login(self): err = self.assertRaises(errors.SnapNotFoundError, self.client.download, 'test-snap-branded-store', 'test-channel', 'dummy') arch = ProjectOptions().deb_arch self.assertEqual( "Snap 'test-snap-branded-store' for '{}' cannot be found in " "the 'test-channel' channel.".format(arch), str(err))
def test_user_agent(self): arch = ProjectOptions().deb_arch expected_pre = 'snapcraft/{} '.format(snapcraft_version) expected_post = ' {} ({})'.format( '/'.join(platform.dist()[0:2]), # i.e. Ubuntu/16.04 arch, ) actual = storeapi._agent.get_user_agent() self.assertTrue(actual.startswith(expected_pre)) self.assertTrue(actual.endswith(expected_post))
def test_cleanbuild(self, mock_pet, mock_inject, mock_container_run): mock_container_run.side_effect = lambda cmd, **kwargs: cmd fake_lxd = tests.fixture_setup.FakeLXD() self.useFixture(fake_lxd) fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(fake_logger) mock_pet.return_value = 'my-pet' project_options = ProjectOptions(target_deb_arch=self.target_arch) metadata = {'name': 'project'} project_folder = '/root/build_project' lxd.Cleanbuilder(output='snap.snap', source='project.tar', metadata=metadata, remote=self.remote, project_options=project_options).execute() expected_arch = 'amd64' self.assertIn('Setting up container with project assets\n' 'Waiting for a network connection...\n' 'Network connection established\n' 'Retrieved snap.snap\n', fake_logger.output) args = [] if self.target_arch: self.assertIn('Setting target machine to \'{}\'\n'.format( self.target_arch), fake_logger.output) args += ['--target-arch', self.target_arch] container_name = '{}:snapcraft-my-pet'.format(self.remote) fake_lxd.check_call_mock.assert_has_calls([ call(['lxc', 'launch', '-e', 'ubuntu:xenial/{}'.format(expected_arch), container_name]), call(['lxc', 'config', 'set', container_name, 'environment.SNAPCRAFT_SETUP_CORE', '1']), call(['lxc', 'config', 'set', container_name, 'environment.LC_ALL', 'C.UTF-8']), call(['lxc', 'file', 'push', os.path.realpath('project.tar'), '{}/root/build_project/project.tar'.format(container_name)]), ]) mock_container_run.assert_has_calls([ call(['mkdir', project_folder]), call(['tar', 'xvf', 'project.tar'], cwd=project_folder), call(['python3', '-c', 'import urllib.request; ' + 'urllib.request.urlopen(' + '"http://start.ubuntu.com/connectivity-check.html"' + ', timeout=5)']), call(['apt-get', 'update']), call(['snapcraft', 'snap', '--output', 'snap.snap', *args], cwd=project_folder), ]) fake_lxd.check_call_mock.assert_has_calls([ call(['lxc', 'file', 'pull', '{}{}/snap.snap'.format(container_name, project_folder), 'snap.snap']), call(['lxc', 'stop', '-f', container_name]), ])
def test_remote_does_not_exist(self, mock_run): self.useFixture(tests.fixture_setup.FakeLXD(fail_on_remote=True)) project_options = ProjectOptions(debug=False) metadata = {'name': 'project'} with ExpectedException(lxd.SnapcraftEnvironmentError, 'There are either.*my-remote.*'): lxd.Cleanbuilder(output='snap.snap', source='project.tar', metadata=metadata, project_options=project_options, remote='my-remote')
def setUp(self): super().setUp() self.fake_lxd = fixture_setup.FakeLXD() self.useFixture(self.fake_lxd) self.fake_lxd.kernel_arch = self.server self.fake_filesystem = fixture_setup.FakeFilesystem() self.useFixture(self.fake_filesystem) self.fake_logger = fixtures.FakeLogger(level=logging.INFO) self.useFixture(self.fake_logger) self.project_options = ProjectOptions(target_deb_arch=self.target_arch)
def test_lxc_check_fails(self, mock_sleep, mock_run): self.check_output_mock.side_effect = check_output_side_effect( fail_on_default=True) project_options = ProjectOptions(debug=False) with ExpectedException( lxd.SnapcraftEnvironmentError, 'You must have LXD installed in order to use cleanbuild. ' 'However, it is either not installed or not configured ' 'properly.\n' 'Refer to the documentation at ' 'https://linuxcontainers.org/lxd/getting-started-cli.'): lxd.Cleanbuilder('snap.snap', 'project.tar', project_options)
def test_failed_build_with_debug(self): def call_effect(*args, **kwargs): if "snapcraft snap --output snap.snap" in " ".join(args[0]): raise CalledProcessError(returncode=255, cmd=args[0]) return self.fake_lxd.check_output_side_effect()(*args, **kwargs) self.fake_lxd.check_call_mock.side_effect = call_effect self.project_options = ProjectOptions(debug=True) self.make_containerbuild().execute() self.fake_lxd.check_call_mock.assert_has_calls( [call(["lxc", "exec", self.fake_lxd.name, "--", "bash", "-i"])])
def test_remote_does_not_exist(self, mock_run): fake_lxd = tests.fixture_setup.FakeLXD() self.useFixture(fake_lxd) fake_lxd.check_output_mock.side_effect = CalledProcessError( 255, ['lxd', 'list', 'my-remote']) project_options = ProjectOptions(debug=False) metadata = {'name': 'project'} with ExpectedException(lxd.SnapcraftEnvironmentError, 'There are either.*my-remote.*'): lxd.Cleanbuilder(output='snap.snap', source='project.tar', metadata=metadata, project_options=project_options, remote='my-remote')
def get_project_options(**kwargs): ctx = click.get_current_context() for key, value in ctx.parent.params.items(): if not kwargs.get(key): kwargs[key] = value project_args = dict( debug=kwargs.pop('debug'), use_geoip=kwargs.pop('enable_geoip'), parallel_builds=not kwargs.pop('no_parallel_builds'), target_deb_arch=kwargs.pop('target_arch'), ) return ProjectOptions(**project_args)
def test_failed_build_with_debug(self, mock_sleep, mock_run): call_list = [] def run_effect(*args, **kwargs): call_list.append(args[0]) if args[0] == ['snapcraft', 'snap', '--output', 'snap.snap']: raise CalledProcessError(returncode=255, cmd=args[0]) mock_run.side_effect = run_effect project_options = ProjectOptions(debug=True) lxd.Cleanbuilder('snap.snap', 'project.tar', project_options).execute() self.assertIn(['bash', '-i'], call_list)
def test_failed_build_with_debug(self): def call_effect(*args, **kwargs): if 'snapcraft snap --output snap.snap' in ' '.join(args[0]): raise CalledProcessError(returncode=255, cmd=args[0]) return self.fake_lxd.check_output_side_effect()(*args, **kwargs) self.fake_lxd.check_call_mock.side_effect = call_effect self.project_options = ProjectOptions(debug=True) self.make_containerbuild().execute() self.fake_lxd.check_call_mock.assert_has_calls([ call(['lxc', 'exec', self.fake_lxd.name, '--', 'bash', '-i']), ])
def test_lxc_check_fails(self, mock_run): fake_lxd = tests.fixture_setup.FakeLXD() self.useFixture(fake_lxd) fake_lxd.check_output_mock.side_effect = FileNotFoundError('lxc') project_options = ProjectOptions(debug=False) metadata = {'name': 'project'} with ExpectedException( lxd.SnapcraftEnvironmentError, 'You must have LXD installed in order to use cleanbuild.\n' 'Refer to the documentation at ' 'https://linuxcontainers.org/lxd/getting-started-cli.'): lxd.Cleanbuilder(output='snap.snap', source='project.tar', metadata=metadata, project_options=project_options)
def test_lxc_check_fails(self, mock_run): self.useFixture(tests.fixture_setup.FakeLXD(fail_on_default=True)) project_options = ProjectOptions(debug=False) metadata = {'name': 'project'} with ExpectedException( lxd.SnapcraftEnvironmentError, 'You must have LXD installed in order to use cleanbuild. ' 'However, it is either not installed or not configured ' 'properly.\n' 'Refer to the documentation at ' 'https://linuxcontainers.org/lxd/getting-started-cli.'): lxd.Cleanbuilder(output='snap.snap', source='project.tar', metadata=metadata, project_options=project_options)
def test_failed_build_with_debug(self, mock_run): self.useFixture(tests.fixture_setup.FakeLXD()) call_list = [] def run_effect(*args, **kwargs): call_list.append(args[0]) if args[0] == ['snapcraft', 'snap', '--output', 'snap.snap']: raise CalledProcessError(returncode=255, cmd=args[0]) mock_run.side_effect = run_effect project_options = ProjectOptions(debug=True) metadata = {'name': 'project'} lxd.Cleanbuilder(output='snap.snap', source='project.tar', metadata=metadata, project_options=project_options).execute() self.assertIn(['bash', '-i'], call_list)
def __init__( self, *, elf_files: FrozenSet[elf.ElfFile], plugin, project: ProjectOptions, confinement: str, # TODO remove once project has this core_base: str, # TODO remove once project has this snap_base_path: str, # TODO remove once project has this stage_packages: List[str], stagedir: str, primedir: str ) -> None: """Initialize PartPatcher. :param elf_files: the list of elf files to analyze. :param plugin: the plugin the part is using. :param project: the project instance from the part. :param confinement: the confinement value the snapcraft project is using (i.e.; devmode, strict, classic). :param core_base: the base the snap will use during runtime (e.g.; core, core18). :param snap_base_path: the root path of the snap during runtime, necessary when using a in-snap libc6 provided as a stage-packages entry. :param stage_packages: the stage-packages a part is set to use. :param stagedir: the general stage directory for the snapcraft project. This is used to locate an alternate patchelf binary to use. :param primedir: the general prime directory for the snapcraft project. """ self._elf_files = elf_files self._is_go_based_plugin = is_go_based_plugin(plugin) self._project = project self._is_classic = confinement == "classic" self._is_host_compat_with_base = project.is_host_compatible_with_base(core_base) self._core_base = core_base self._snap_base_path = snap_base_path # If libc6 is staged, to avoid symbol mixups we will resort to # glibc mangling. self._is_libc6_staged = "libc6" in stage_packages self._stagedir = stagedir self._primedir = primedir
def __init__( self, *, elf_files: FrozenSet[elf.ElfFile], plugin, project: ProjectOptions, confinement: str, # TODO remove once project has this core_base: str, # TODO remove once project has this snap_base_path: str, # TODO remove once project has this stage_packages: List[str], stagedir: str, primedir: str) -> None: """Initialize PartPatcher. :param elf_files: the list of elf files to analyze. :param plugin: the plugin the part is using. :param project: the project instance from the part. :param confinement: the confinement value the snapcraft project is using (i.e.; devmode, strict, classic). :param core_base: the base the snap will use during runtime (e.g.; core, core18). :param snap_base_path: the root path of the snap during runtime, necessary when using a in-snap libc6 provided as a stage-packages entry. :param stage_packages: the stage-packages a part is set to use. :param stagedir: the general stage directory for the snapcraft project. This is used to locate an alternate patchelf binary to use. :param primedir: the general prime directory for the snapcraft project. """ self._elf_files = elf_files self._is_go_based_plugin = is_go_based_plugin(plugin) self._project = project self._is_classic = confinement == 'classic' self._is_host_compat_with_base = project.is_host_compatible_with_base( core_base) self._core_base = core_base self._snap_base_path = snap_base_path # If libc6 is staged, to avoid symbol mixups we will resort to # glibc mangling. self._is_libc6_staged = 'libc6' in stage_packages self._stagedir = stagedir self._primedir = primedir
def test_failed_container_never_created(self): fake_lxd = tests.fixture_setup.FakeLXD() self.useFixture(fake_lxd) def call_effect(*args, **kwargs): if args[0][:2] == ['lxc', 'launch']: raise CalledProcessError(returncode=255, cmd=args[0]) return fake_lxd.check_output_side_effect()(*args, **kwargs) fake_lxd.check_call_mock.side_effect = call_effect metadata = {'name': 'project'} raised = self.assertRaises( CalledProcessError, lxd.Cleanbuilder(output='snap.snap', source='project.tar', metadata=metadata, project_options=ProjectOptions()).execute) self.assertEquals(fake_lxd.status, None) # lxc launch should fail and no further commands should come after that self.assertThat(str(raised), Contains("Command '['lxc', 'launch'"))