diff --git a/snapcraft/plugins/maven.py b/snapcraft/plugins/maven.py index a09da60efb5..65fad19650e 100644 --- a/snapcraft/plugins/maven.py +++ b/snapcraft/plugins/maven.py @@ -59,9 +59,20 @@ def schema(cls): 'default': [], } + schema['properties']['maven-targets'] = { + 'type': 'array', + 'minitems': 1, + 'uniqueItems': True, + 'items': { + 'type': 'string', + }, + 'default': [''], + } + # Inform Snapcraft of the properties associated with building. If these # change in the YAML Snapcraft will consider the build step dirty. schema['build-properties'].append('maven-options') + schema['build-properties'].append('maven-targets') return schema @@ -83,18 +94,27 @@ def build(self): self.run(mvn_cmd + self.options.maven_options) - jarfiles = glob.glob(os.path.join(self.builddir, 'target', '*.jar')) - warfiles = glob.glob(os.path.join(self.builddir, 'target', '*.war')) - if not (jarfiles or warfiles): - raise RuntimeError('could not find any built jar files for part') - if jarfiles: - jardir = os.path.join(self.installdir, 'jar') - os.makedirs(jardir, exist_ok=True) - self.run(['cp', '-a'] + jarfiles + [jardir]) - if warfiles: - wardir = os.path.join(self.installdir, 'war') - os.makedirs(wardir, exist_ok=True) - self.run(['cp', '-a'] + warfiles + [wardir]) + for f in self.options.maven_targets: + src = os.path.join(self.builddir, f, 'target') + jarfiles = glob.glob(os.path.join(src, '*.jar')) + warfiles = glob.glob(os.path.join(src, '*.war')) + arfiles = glob.glob(os.path.join(src, '*.[jw]ar')) + + if len(arfiles) == 0: + raise RuntimeError("could not find any" + "built jar files for part") + if len(jarfiles) > 0 and len(f) == 0: + basedir = 'jar' + elif len(warfiles) > 0 and len(f) == 0: + basedir = 'war' + else: + basedir = f + + targetdir = os.path.join(self.installdir, basedir) + os.makedirs(targetdir, exist_ok=True) + for f in arfiles: + base = os.path.basename(f) + os.link(f, os.path.join(targetdir, base)) def _create_settings(settings_path): diff --git a/snapcraft/tests/test_plugin_maven.py b/snapcraft/tests/test_plugin_maven.py index 6b816b46bfb..c19215e7d38 100644 --- a/snapcraft/tests/test_plugin_maven.py +++ b/snapcraft/tests/test_plugin_maven.py @@ -33,6 +33,7 @@ def setUp(self): class Options: maven_options = [] + maven_targets = [''] self.options = Options() self.project_options = snapcraft.ProjectOptions() @@ -94,12 +95,34 @@ def test_schema(self): maven_options['uniqueItems'], 'Expected "maven-options" "uniqueItems" to be "True"') + maven_targets = properties['maven-targets'] + + self.assertTrue( + 'type' in maven_targets, + 'Expected "type" to be included in "maven-targets"') + self.assertEqual(maven_targets['type'], 'array', + 'Expected "maven-targets" "type" to be "array", but ' + 'it was "{}"'.format(maven_targets['type'])) + + self.assertTrue( + 'minitems' in maven_targets, + 'Expected "minitems" to be included in "maven-targets"') + self.assertEqual(maven_targets['minitems'], 1, + 'Expected "maven-targets" "minitems" to be 1, but ' + 'it was "{}"'.format(maven_targets['minitems'])) + + self.assertTrue( + 'uniqueItems' in maven_targets, + 'Expected "uniqueItems" to be included in "maven-targets"') + self.assertTrue( + maven_targets['uniqueItems'], + 'Expected "maven-targets" "uniqueItems" to be "True"') + build_properties = schema['build-properties'] - self.assertEqual(['maven-options'], build_properties) + self.assertEqual(['maven-options', 'maven-targets'], build_properties) @mock.patch.object(maven.MavenPlugin, 'run') - @mock.patch('glob.glob') - def test_build(self, glob_mock, run_mock): + def test_build(self, run_mock): env_vars = ( ('http_proxy', None), ('https_proxy', None), @@ -109,9 +132,14 @@ def test_build(self, glob_mock, run_mock): plugin = maven.MavenPlugin('test-part', self.options, self.project_options) + + def side(l): + os.makedirs(os.path.join(plugin.builddir, 'target')) + open(os.path.join(plugin.builddir, + 'target', 'dummy.jar'), 'w').close() + + run_mock.side_effect = side os.makedirs(plugin.sourcedir) - glob_mock.return_value = [ - os.path.join(plugin.builddir, 'target', 'dummy')] plugin.build() @@ -120,8 +148,87 @@ def test_build(self, glob_mock, run_mock): ]) @mock.patch.object(maven.MavenPlugin, 'run') - @mock.patch('glob.glob') - def test_build_with_http_proxy(self, glob_mock, run_mock): + def test_build_fail(self, run_mock): + env_vars = ( + ('http_proxy', None), + ('https_proxy', None), + ) + for v in env_vars: + self.useFixture(fixtures.EnvironmentVariable(v[0], v[1])) + + plugin = maven.MavenPlugin('test-part', self.options, + self.project_options) + + os.makedirs(plugin.sourcedir) + + with self.assertRaises(RuntimeError): + plugin.build() + + run_mock.assert_has_calls([ + mock.call(['mvn', 'package']), + ]) + + @mock.patch.object(maven.MavenPlugin, 'run') + def test_build_war(self, run_mock): + env_vars = ( + ('http_proxy', None), + ('https_proxy', None), + ) + for v in env_vars: + self.useFixture(fixtures.EnvironmentVariable(v[0], v[1])) + + plugin = maven.MavenPlugin('test-part', self.options, + self.project_options) + + def side(l): + os.makedirs(os.path.join(plugin.builddir, 'target')) + open(os.path.join(plugin.builddir, + 'target', 'dummy.war'), 'w').close() + + run_mock.side_effect = side + os.makedirs(plugin.sourcedir) + + plugin.build() + + run_mock.assert_has_calls([ + mock.call(['mvn', 'package']), + ]) + + @mock.patch.object(maven.MavenPlugin, 'run') + def test_build_with_targets(self, run_mock): + env_vars = ( + ('http_proxy', None), + ('https_proxy', None), + ) + for v in env_vars: + self.useFixture(fixtures.EnvironmentVariable(v[0], v[1])) + + opts = self.options + opts.maven_targets = ['child1', 'child2'] + plugin = maven.MavenPlugin('test-part', opts, + self.project_options) + + def side(l): + os.makedirs(os.path.join(plugin.builddir, + 'child1', 'target')) + os.makedirs(os.path.join(plugin.builddir, + 'child2', 'target')) + open(os.path.join(plugin.builddir, + 'child1', 'target', 'child1.jar'), 'w').close() + open(os.path.join(plugin.builddir, + 'child2', 'target', 'child2.jar'), 'w').close() + + run_mock.side_effect = side + os.makedirs(plugin.sourcedir) + + plugin.build() + + run_mock.assert_has_calls([ + mock.call(['mvn', 'package']), + ]) + + @mock.patch.object(maven.MavenPlugin, 'run') + def test_build_with_http_proxy(self, run_mock): env_vars = ( ('http_proxy', 'http://localhost:3132'), ('https_proxy', None), @@ -133,10 +240,14 @@ def test_build_with_http_proxy(self, glob_mock, run_mock): plugin = maven.MavenPlugin('test-part', self.options, self.project_options) + def side(l): + os.makedirs(os.path.join(plugin.builddir, 'target')) + open(os.path.join(plugin.builddir, + 'target', 'dummy.jar'), 'w').close() + + run_mock.side_effect = side settings_path = os.path.join(plugin.partdir, 'm2', 'settings.xml') os.makedirs(plugin.sourcedir) - glob_mock.return_value = [ - os.path.join(plugin.builddir, 'target', 'dummy')] plugin.build() @@ -171,8 +282,7 @@ def test_build_with_http_proxy(self, glob_mock, run_mock): self.assertSettingsEqual(expected_contents, settings_contents) @mock.patch.object(maven.MavenPlugin, 'run') - @mock.patch('glob.glob') - def test_build_with_http_proxy_and_no_proxy(self, glob_mock, run_mock): + def test_build_with_http_proxy_and_no_proxy(self, run_mock): env_vars = ( ('http_proxy', 'http://localhost:3132'), ('https_proxy', None), @@ -184,10 +294,14 @@ def test_build_with_http_proxy_and_no_proxy(self, glob_mock, run_mock): plugin = maven.MavenPlugin('test-part', self.options, self.project_options) + def side(l): + os.makedirs(os.path.join(plugin.builddir, 'target')) + open(os.path.join(plugin.builddir, + 'target', 'dummy.jar'), 'w').close() + + run_mock.side_effect = side settings_path = os.path.join(plugin.partdir, 'm2', 'settings.xml') os.makedirs(plugin.sourcedir) - glob_mock.return_value = [ - os.path.join(plugin.builddir, 'target', 'dummy')] plugin.build() @@ -222,8 +336,7 @@ def test_build_with_http_proxy_and_no_proxy(self, glob_mock, run_mock): self.assertSettingsEqual(expected_contents, settings_contents) @mock.patch.object(maven.MavenPlugin, 'run') - @mock.patch('glob.glob') - def test_build_with_http_proxy_and_no_proxies(self, glob_mock, run_mock): + def test_build_with_http_proxy_and_no_proxies(self, run_mock): env_vars = ( ('http_proxy', 'http://localhost:3132'), ('https_proxy', None), @@ -235,10 +348,14 @@ def test_build_with_http_proxy_and_no_proxies(self, glob_mock, run_mock): plugin = maven.MavenPlugin('test-part', self.options, self.project_options) + def side(l): + os.makedirs(os.path.join(plugin.builddir, 'target')) + open(os.path.join(plugin.builddir, + 'target', 'dummy.jar'), 'w').close() + + run_mock.side_effect = side settings_path = os.path.join(plugin.partdir, 'm2', 'settings.xml') os.makedirs(plugin.sourcedir) - glob_mock.return_value = [ - os.path.join(plugin.builddir, 'target', 'dummy')] plugin.build() @@ -273,8 +390,7 @@ def test_build_with_http_proxy_and_no_proxies(self, glob_mock, run_mock): self.assertSettingsEqual(expected_contents, settings_contents) @mock.patch.object(maven.MavenPlugin, 'run') - @mock.patch('glob.glob') - def test_build_with_http_and_https_proxy(self, glob_mock, run_mock): + def test_build_with_http_and_https_proxy(self, run_mock): env_vars = ( ('http_proxy', 'http://localhost:3132'), ('https_proxy', 'http://localhost:3133'), @@ -286,10 +402,14 @@ def test_build_with_http_and_https_proxy(self, glob_mock, run_mock): plugin = maven.MavenPlugin('test-part', self.options, self.project_options) + def side(l): + os.makedirs(os.path.join(plugin.builddir, 'target')) + open(os.path.join(plugin.builddir, + 'target', 'dummy.jar'), 'w').close() + + run_mock.side_effect = side settings_path = os.path.join(plugin.partdir, 'm2', 'settings.xml') os.makedirs(plugin.sourcedir) - glob_mock.return_value = [ - os.path.join(plugin.builddir, 'target', 'dummy')] plugin.build() @@ -332,8 +452,7 @@ def test_build_with_http_and_https_proxy(self, glob_mock, run_mock): self.assertSettingsEqual(expected_contents, settings_contents) @mock.patch.object(maven.MavenPlugin, 'run') - @mock.patch('glob.glob') - def test_build_with_authenticated_proxies(self, glob_mock, run_mock): + def test_build_with_authenticated_proxies(self, run_mock): env_vars = ( ('http_proxy', 'http://user1:pass1@localhost:3132'), ('https_proxy', 'http://user2:pass2@localhost:3133'), @@ -345,10 +464,14 @@ def test_build_with_authenticated_proxies(self, glob_mock, run_mock): plugin = maven.MavenPlugin('test-part', self.options, self.project_options) + def side(l): + os.makedirs(os.path.join(plugin.builddir, 'target')) + open(os.path.join(plugin.builddir, + 'target', 'dummy.jar'), 'w').close() + + run_mock.side_effect = side settings_path = os.path.join(plugin.partdir, 'm2', 'settings.xml') os.makedirs(plugin.sourcedir) - glob_mock.return_value = [ - os.path.join(plugin.builddir, 'target', 'dummy')] plugin.build() diff --git a/snaps_tests/__init__.py b/snaps_tests/__init__.py index 0005a84aa1e..b25d81397fd 100644 --- a/snaps_tests/__init__.py +++ b/snaps_tests/__init__.py @@ -25,6 +25,7 @@ import subprocess import sys +import fixtures import pexpect import testtools from testtools import content @@ -118,6 +119,10 @@ def setUp(self): self.snapcraft_command = os.path.join( os.getcwd(), 'bin', 'snapcraft') + temp_dir = fixtures.TempDir() + self.useFixture(temp_dir) + self.path = temp_dir.path + self.snappy_testbed = None if not config.get('skip-install', False): ip = config.get('ip', None) @@ -150,13 +155,14 @@ def _set_up_qemu_testbed(self): return snappy_testbed def build_snap(self, snap_content_dir): - working_dir = os.path.join(self.src_dir, snap_content_dir) - self._clean(working_dir) - self._snap(working_dir) + project_dir = os.path.join(self.src_dir, snap_content_dir) + tmp_project_dir = os.path.join(self.path, snap_content_dir) + shutil.copytree(project_dir, tmp_project_dir, symlinks=True) + + self._snap(tmp_project_dir) - def _clean(self, project_dir): - command = '{} {}'.format(self.snapcraft_command, 'clean') - self._run_command(command, project_dir) + snap_glob_path = os.path.join(tmp_project_dir, '*.snap') + return glob.glob(snap_glob_path)[0] def _snap(self, project_dir): command = '{} {}'.format(self.snapcraft_command, 'snap') @@ -187,15 +193,11 @@ def _run_command( def _add_output_detail(self, output): self.addDetail('output', content.text_content(str(output))) - def install_snap(self, snap_content_dir, snap_name, version, + def install_snap(self, snap_local_path, snap_name, version, devmode=False): if not config.get('skip-install', False): - snap_file_name = '{}_{}_*.snap'.format( - snap_name, version) - snap_local_glob_path = os.path.join( - self.src_dir, snap_content_dir, snap_file_name) - snap_local_path = glob.glob(snap_local_glob_path)[0] self.snappy_testbed.copy_file(snap_local_path, '/home/ubuntu') + snap_file_name = os.path.basename(snap_local_path) snap_path_in_testbed = os.path.join( '/home/ubuntu/', snap_file_name) # Remove the snap file from the testbed. diff --git a/snaps_tests/demos_tests/test_busybox.py b/snaps_tests/demos_tests/test_busybox.py index fe35a89b963..fcce1b870a5 100644 --- a/snaps_tests/demos_tests/test_busybox.py +++ b/snaps_tests/demos_tests/test_busybox.py @@ -22,8 +22,8 @@ class BusyBoxTestCase(snaps_tests.SnapsTestCase): snap_content_dir = 'busybox' def test_busybox(self): - self.build_snap(self.snap_content_dir) - self.install_snap(self.snap_content_dir, 'busybox', '1.0') + snap_path = self.build_snap(self.snap_content_dir) + self.install_snap(snap_path, 'busybox', '1.0') # Run the binary once to create the data dir. self.run_command_in_snappy_testbed([ '/snap/bin/busybox.touch', '/tmp/']) diff --git a/snaps_tests/demos_tests/test_downloader_with_wiki_parts.py b/snaps_tests/demos_tests/test_downloader_with_wiki_parts.py index 23a5c04b9b7..5b95575af95 100644 --- a/snaps_tests/demos_tests/test_downloader_with_wiki_parts.py +++ b/snaps_tests/demos_tests/test_downloader_with_wiki_parts.py @@ -24,8 +24,8 @@ class DownloaderWithWikiPartsTestCase(snaps_tests.SnapsTestCase): snap_content_dir = 'downloader-with-wiki-parts' def test_downloader_with_wiki_parts(self): - self.build_snap(self.snap_content_dir) - self.install_snap(self.snap_content_dir, 'downloader', '1.0') + snap_path = self.build_snap(self.snap_content_dir) + self.install_snap(snap_path, 'downloader', '1.0') expected = ( '.*