diff --git a/pungi/ostree/__init__.py b/pungi/ostree/__init__.py index fe8c53ea..f5d2055c 100644 --- a/pungi/ostree/__init__.py +++ b/pungi/ostree/__init__.py @@ -17,6 +17,7 @@ import argparse from .tree import Tree +from .installer import Installer def main(args=None): @@ -38,6 +39,44 @@ def main(args=None): treep.add_argument('--update-summary', action='store_true', help='update summary metadata') + installerp = subparser.add_parser("installer", help="Create an OSTree installer image") + installerp.set_defaults(_class=Installer, func='run') + installerp.add_argument('-p', '--product', metavar='PRODUCT', required=True, + help='product name (required)') + installerp.add_argument('-v', '--version', metavar='VERSION', required=True, + help='version identifier (required)') + installerp.add_argument('-r', '--release', metavar='RELEASE', required=True, + help='release information (required)') + installerp.add_argument('-s', '--source', metavar='REPOSITORY', required=True, + action='append', + help='source repository (required)') + installerp.add_argument('-o', '--output', metavar='DIR', required=True, + help='path to image output directory (required)') + installerp.add_argument('--log-dir', metavar='DIR', + help='path to log directory') + installerp.add_argument('--volid', metavar='VOLID', + help='volume id') + installerp.add_argument('--variant', metavar='VARIANT', + help='variant name') + installerp.add_argument('--rootfs-size', metavar='SIZE') + installerp.add_argument('--nomacboot', action='store_true', default=False) + installerp.add_argument('--noupgrade', action='store_true', default=False) + installerp.add_argument('--isfinal', action='store_true', default=False) + + installerp.add_argument('--installpkgs', metavar='PACKAGE', action='append', + help='package glob to install before runtime-install.tmpl') + installerp.add_argument('--add-template', metavar='FILE', action='append', + help='Additional template for runtime image') + installerp.add_argument('--add-template-var', metavar='ADD_TEMPLATE_VARS', action='append', + help='Set variable for runtime image template') + installerp.add_argument('--add-arch-template', metavar='FILE', action='append', + help='Additional template for architecture-specific image') + installerp.add_argument('--add-arch-template-var', metavar='ADD_ARCH_TEMPLATE_VARS', action='append', + help='Set variable for architecture-specific image') + + installerp.add_argument('--extra-config', metavar='FILE', + help='JSON file contains extra configurations') + args = parser.parse_args(args) _class = args._class() _class.set_args(args) diff --git a/pungi/ostree/installer.py b/pungi/ostree/installer.py new file mode 100644 index 00000000..074183f8 --- /dev/null +++ b/pungi/ostree/installer.py @@ -0,0 +1,80 @@ +# -*- coding: utf-8 -*- + + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Library General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, see . + + +import json +from kobo import shortcuts + +from .base import OSTree +from ..wrappers import lorax + + +class Installer(OSTree): + def _merge_config(self, config): + if config.get("source_repo_from", None): + self.sources.extend([config.get("source_repo_from")]) + + self.installpkgs.extend(config.get('installpkgs', [])) + self.add_template.extend(config.get("add_template", [])) + self.add_template_var.extend(config.get("add_template_var")) + self.add_arch_template.extend(config.get("add_arch_template", [])) + self.add_arch_template_var.extend(config.get("add_arch_template_var", [])) + + def run(self): + self.product = self.args.product + self.version = self.args.version + self.release = self.args.release + self.sources = self.args.source + self.output = self.args.output + + self.logdir = self.args.log_dir + self.volid = self.args.volid + self.variant = self.args.variant + self.rootfs_size = self.args.rootfs_size + self.nomacboot = self.args.nomacboot + self.noupgrade = self.args.noupgrade + self.isfinal = self.args.isfinal + + self.installpkgs = self.args.installpkgs or [] + self.add_template = self.args.add_template or [] + self.add_template_var = self.args.add_template_var or [] + self.add_arch_template = self.args.add_arch_template or [] + self.add_arch_template_var = self.args.add_arch_template_var or [] + + self.extra_config = self.args.extra_config + if self.extra_config: + self.extra_config = json.load(open(self.extra_config, 'r')) + self._merge_config(self.extra_config) + + lorax_wrapper = lorax.LoraxWrapper() + cmd = lorax_wrapper.get_lorax_cmd( + self.product, + self.version, + self.release, + self.sources, + self.output, + variant=self.variant, + nomacboot=self.nomacboot, + volid=self.volid, + buildinstallpackages=self.installpkgs, + add_template=self.add_template, + add_template_var=self.add_template_var, + add_arch_template=self.add_arch_template, + add_arch_template_var=self.add_arch_template_var, + rootfs_size=self.rootfs_size, + is_final=self.isfinal, + log_dir=self.logdir + ) + shortcuts.run(cmd) diff --git a/tests/test_ostree_script.py b/tests/test_ostree_script.py index 735a8fb7..94868c7e 100644 --- a/tests/test_ostree_script.py +++ b/tests/test_ostree_script.py @@ -266,5 +266,102 @@ class OstreeTreeScriptTest(helpers.PungiTestCase): source_repo_from_name, optional_repo_name, extra_repo_name]: self.assertIn(name, repos) + +class OstreeInstallerScriptTest(helpers.PungiTestCase): + def setUp(self): + super(OstreeInstallerScriptTest, self).setUp() + self.product = "dummyproduct" + self.version = "1.0" + self.release = "20160101.t.0" + self.output = os.path.join(self.topdir, 'output') + self.logdir = os.path.join(self.topdir, 'logs') + self.volid = '%s-%s' % (self.product, self.version) + self.variant = 'dummy' + self.rootfs_size = None + + @mock.patch('kobo.shortcuts.run') + def test_run_with_args(self, run): + args = ['installer', + '--product=%s' % self.product, + '--version=%s' % self.version, + '--release=%s' % self.release, + '--output=%s' % self.output, + '--variant=%s' % self.variant, + '--rootfs-size=%s' % self.rootfs_size, + '--nomacboot', + '--isfinal'] + args.append('--source=%s' % 'http://www.example.com/dummy/repo') + args.append('--installpkgs=dummy-foo') + args.append('--installpkgs=dummy-bar') + args.append('--add-template=/path/to/lorax.tmpl') + args.append('--add-template-var=ostree_osname=dummy') + args.append('--add-arch-template=/path/to/lorax-embed.tmpl') + args.append('--add-arch-template-var=ostree_repo=http://www.example.com/ostree') + ostree.main(args) + self.maxDiff = None + self.assertItemsEqual(run.mock_calls, + [mock.call(['lorax', + '--product=dummyproduct', + '--version=1.0', + '--release=20160101.t.0', + '--source=http://www.example.com/dummy/repo', + '--variant=dummy', + '--nomacboot', + '--isfinal', + '--installpkgs=dummy-foo', + '--installpkgs=dummy-bar', + '--add-template=/path/to/lorax.tmpl', + '--add-arch-template=/path/to/lorax-embed.tmpl', + '--add-template-var=ostree_osname=dummy', + '--add-arch-template-var=ostree_repo=http://www.example.com/ostree', + '--rootfs-size=None', + self.output])]) + + @mock.patch('kobo.shortcuts.run') + def test_run_with_extra_config_file(self, run): + extra_config_file = os.path.join(self.topdir, 'extra_config.json') + helpers.touch(extra_config_file, + json.dumps({'source_repo_from': 'http://www.example.com/another/repo', + 'installpkgs': ['dummy-foo', 'dummy-bar'], + 'add_template': ['/path/to/lorax.tmpl'], + 'add_template_var': ['ostree_osname=dummy-atomic', + 'ostree_ref=dummy/x86_64/docker'], + 'add_arch_template': ['/path/to/lorax-embed.tmpl'], + 'add_arch_template_var': ['ostree_osname=dummy-atomic', + 'ostree_repo=http://www.example.com/ostree']})) + args = ['installer', + '--product=%s' % self.product, + '--version=%s' % self.version, + '--release=%s' % self.release, + '--output=%s' % self.output, + '--variant=%s' % self.variant, + '--rootfs-size=%s' % self.rootfs_size, + '--nomacboot', + '--isfinal'] + args.append('--source=%s' % 'http://www.example.com/dummy/repo') + args.append('--extra-config=%s' % extra_config_file) + ostree.main(args) + self.maxDiff = None + self.assertItemsEqual(run.mock_calls, + [mock.call(['lorax', + '--product=dummyproduct', + '--version=1.0', + '--release=20160101.t.0', + '--source=http://www.example.com/dummy/repo', + '--source=http://www.example.com/another/repo', + '--variant=dummy', + '--nomacboot', + '--isfinal', + '--installpkgs=dummy-foo', + '--installpkgs=dummy-bar', + '--add-template=/path/to/lorax.tmpl', + '--add-arch-template=/path/to/lorax-embed.tmpl', + '--add-template-var=ostree_osname=dummy-atomic', + '--add-template-var=ostree_ref=dummy/x86_64/docker', + '--add-arch-template-var=ostree_osname=dummy-atomic', + '--add-arch-template-var=ostree_repo=http://www.example.com/ostree', + '--rootfs-size=None', + self.output])]) + if __name__ == '__main__': unittest.main()