Hello community, here is the log from the commit of package python-kiwi for openSUSE:Factory checked in at 2017-03-20 17:08:56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-kiwi (Old) and /work/SRC/openSUSE:Factory/.python-kiwi.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-kiwi" Mon Mar 20 17:08:56 2017 rev:2 rq:479991 version:9.4.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-kiwi/python-kiwi.changes 2017-03-16 09:50:56.174879810 +0100 +++ /work/SRC/openSUSE:Factory/.python-kiwi.new/python-kiwi.changes 2017-03-20 17:08:57.646970456 +0100 @@ -1,0 +2,49 @@ +Thu Mar 16 09:45:14 CET 2017 - m...@suse.com + +- Bump version: 9.3.3 → 9.4.0 + +------------------------------------------------------------------- +Wed Mar 15 17:27:38 CET 2017 - m...@suse.com + +- Allow https location as repository source + +------------------------------------------------------------------- +Wed Mar 15 09:47:35 CET 2017 - dcass...@suse.com + +- Refactor RootImport to keep images with a default name + + RootImport has been refactored so the image is kept with a known + name that can be obtained with the Defaults class. + +------------------------------------------------------------------- +Tue Mar 14 16:14:52 CET 2017 - m...@suse.com + +- Added SLE13 distribution matcher + +------------------------------------------------------------------- +Tue Mar 14 16:14:17 CET 2017 - m...@suse.com + +- Update distribution matcher in spec file + +------------------------------------------------------------------- +Tue Mar 14 10:22:59 CET 2017 - m...@suse.com + +- Refactor ContainerBuilder + + Use Checksum instance to run a checksum match + Check for existence of base image at earliest opportunity + when constructing a ContainerBuilder + +------------------------------------------------------------------- +Tue Mar 14 10:22:06 CET 2017 - m...@suse.com + +- Added checksum matcher method to Checksum class + +------------------------------------------------------------------- +Tue Mar 14 10:20:44 CET 2017 - m...@suse.com + +- Delete unused code + + Also fixed corresponding unit test + +------------------------------------------------------------------- @@ -6,0 +56,5 @@ +Mon Mar 13 15:45:32 CET 2017 - m...@suse.com + +- Handle derived image as Uri instance + +------------------------------------------------------------------- @@ -33,0 +88,11 @@ +Thu Mar 9 13:46:05 CET 2017 - dcass...@suse.com + +- Refactored RootImport and included checksum validation + + First, commit refactors RootImport in order to also copy + the imported image after sychronizing the import. + + Second, it includes a checksum of the copied image which is + validated in later steps. + +------------------------------------------------------------------- @@ -56,0 +122,9 @@ + +------------------------------------------------------------------- +Wed Mar 8 09:32:02 CET 2017 - dcass...@suse.com + +- Support for layered docker images + + This commit includes support for building layered docker. A new + layer is added on top of the base image referenced by `derived_from` + attribute. ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-kiwi.spec ++++++ --- /var/tmp/diff_new_pack.zFWKb4/_old 2017-03-20 17:09:00.250602824 +0100 +++ /var/tmp/diff_new_pack.zFWKb4/_new 2017-03-20 17:09:00.254602259 +0100 @@ -1,7 +1,7 @@ # -# spec file for package kiwi +# spec file for package python-kiwi # -# Copyright (c) 2016 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -11,35 +11,49 @@ # case the license is the MIT License). An "Open Source License" is a # license that conforms to the Open Source Definition (Version 1.9) # published by the Open Source Initiative. + +# Please submit bugfixes or comments via http://bugs.opensuse.org/ # -# Please submit bugfixes or comments via: -# -# https://github.com/SUSE/kiwi/issues -# + + %{!?python2_sitelib:%global python2_sitelib %{python_sitelib}} # translate version id to distribution name as it is used in kiwi +# generic approach %if 0%{?suse_version} %define distro %(echo `export VER=%{suse_version}; echo "suse-${VER:0:2}.${VER:2:1}"`) -# redefine for the SLES case if no sles_version exists +%endif + # SLE12: %if 0%{?suse_version} == 1315 && !0%{?is_opensuse} %define distro suse-SLES12 %endif -# Leap 42.1: -%if 0%{?suse_version} == 1315 && 0%{?is_opensuse} + +# SLE13: +%if 0%{?sle_version} == 130000 && !0%{?is_opensuse} +%define distro suse-SLES13 +%endif + +# Leap 42.1(openSUSE product based on SLE 12SP1): +%if 0%{?is_opensuse} && 0%{?sle_version} == 120100 %define distro suse-leap42.1 %endif + # Leap 42.2: -%if 0%{?suse_version} == 1316 && 0%{?is_opensuse} +%if 0%{?leap_version} == 420200 %define distro suse-leap42.2 %endif + +# Leap 42.3: +%if 0%{?leap_version} == 420300 +%define distro suse-leap42.3 +%endif + # Tumbleweed: # Current Tumbleweed version, moving target %if 0%{?suse_version} == 1330 %define distro suse-tumbleweed %endif -%endif # SLES with sles_version macro %if 0%{?sles_version} @@ -52,11 +66,10 @@ %define distro rhel-07.0 %endif - Name: python-kiwi -Version: 9.3.3 -Provides: kiwi-schema = 6.5 +Version: 9.4.0 Release: 0 +Provides: kiwi-schema = 6.5 Url: https://github.com/SUSE/kiwi Summary: KIWI - Appliance Builder Next Generation License: GPL-3.0+ @@ -65,13 +78,13 @@ Source1: %{name}-boot-packages Source2: %{name}-rpmlintrc BuildRoot: %{_tmppath}/%{name}-%{version}-build -BuildRequires: python3-devel -BuildRequires: python3-setuptools +BuildRequires: fdupes BuildRequires: python-devel BuildRequires: python-setuptools -BuildRequires: fdupes -BuildRequires: update-alternatives +BuildRequires: python3-devel +BuildRequires: python3-setuptools BuildRequires: shadow +BuildRequires: update-alternatives %description The KIWI Image System provides an operating system image builder @@ -82,47 +95,47 @@ %package -n python2-kiwi Summary: KIWI - Appliance Builder Next Generation Group: Development/Languages/Python -Provides: python-kiwi = %{version}-%{release} -Provides: kiwi-image:tbz Provides: kiwi-image:docker Provides: kiwi-image:iso -Provides: kiwi-image:vmx -Provides: kiwi-image:pxe Provides: kiwi-image:oem -Requires: update-alternatives +Provides: kiwi-image:pxe +Provides: kiwi-image:tbz +Provides: kiwi-image:vmx +Provides: python-kiwi = %{version}-%{release} Requires: python-docopt -Requires: python-setuptools +Requires: python-future Requires: python-lxml -Requires: python-xattr +Requires: python-setuptools Requires: python-six -Requires: python-future +Requires: python-xattr +Requires: update-alternatives Requires(post): update-alternatives Requires(postun): update-alternatives # tools used by kiwi %if 0%{?suse_version} -Requires: zypper Requires: squashfs +Requires: zypper Provides: kiwi-packagemanager:zypper %endif %if 0%{?rhel_version} || 0%{?centos_version} -Requires: yum Requires: squashfs-tools +Requires: yum Provides: kiwi-packagemanager:yum %endif -Requires: genisoimage -Requires: kiwi-tools -Requires: kiwi-man-pages -Requires: rsync -Requires: tar >= 1.2.7 -Requires: gptfdisk -Requires: qemu-tools Requires: dosfstools Requires: e2fsprogs -Requires: lvm2 -Requires: parted -Requires: multipath-tools +Requires: genisoimage +Requires: gptfdisk Requires: grub2 +Requires: kiwi-man-pages +Requires: kiwi-tools +Requires: lvm2 Requires: mtools +Requires: multipath-tools +Requires: parted +Requires: qemu-tools +Requires: rsync +Requires: tar >= 1.2.7 %ifarch %arm aarch64 Requires: u-boot-tools %endif @@ -142,46 +155,46 @@ %package -n python3-kiwi Summary: KIWI - Appliance Builder Next Generation Group: Development/Languages/Python -Provides: kiwi-image:tbz Provides: kiwi-image:docker Provides: kiwi-image:iso -Provides: kiwi-image:vmx -Provides: kiwi-image:pxe Provides: kiwi-image:oem -Requires: update-alternatives +Provides: kiwi-image:pxe +Provides: kiwi-image:tbz +Provides: kiwi-image:vmx Requires: python3-docopt -Requires: python3-setuptools +Requires: python3-future Requires: python3-lxml -Requires: python3-xattr +Requires: python3-setuptools Requires: python3-six -Requires: python3-future +Requires: python3-xattr +Requires: update-alternatives Requires(post): update-alternatives Requires(postun): update-alternatives # tools used by kiwi %if 0%{?suse_version} -Requires: zypper Requires: squashfs +Requires: zypper Provides: kiwi-packagemanager:zypper %endif %if 0%{?rhel_version} || 0%{?centos_version} -Requires: yum Requires: squashfs-tools +Requires: yum Provides: kiwi-packagemanager:yum %endif -Requires: genisoimage -Requires: kiwi-tools -Requires: kiwi-man-pages -Requires: rsync -Requires: tar >= 1.2.7 -Requires: gptfdisk -Requires: qemu-tools Requires: dosfstools Requires: e2fsprogs -Requires: lvm2 -Requires: parted -Requires: multipath-tools +Requires: genisoimage +Requires: gptfdisk Requires: grub2 +Requires: kiwi-man-pages +Requires: kiwi-tools +Requires: lvm2 Requires: mtools +Requires: multipath-tools +Requires: parted +Requires: qemu-tools +Requires: rsync +Requires: tar >= 1.2.7 %ifarch %arm aarch64 Requires: u-boot-tools %endif @@ -199,7 +212,6 @@ %package -n kiwi-tools Summary: KIWI - Collection of Boot Helper Tools -License: GPL-3.0+ Group: System/Management %description -n kiwi-tools @@ -211,9 +223,8 @@ %ifarch %ix86 x86_64 %package -n kiwi-pxeboot Summary: KIWI - PXE boot structure -Requires: syslinux -License: GPL-3.0+ Group: System/Management +Requires: syslinux %description -n kiwi-pxeboot This package contains the basic PXE directory structure which is @@ -222,22 +233,21 @@ %package -n kiwi-boot-requires Summary: KIWI - buildservice package requirements for boot images +Group: System/Management Provides: kiwi-boot:isoboot -Provides: kiwi-boot:vmxboot Provides: kiwi-boot:netboot Provides: kiwi-boot:oemboot +Provides: kiwi-boot:vmxboot Provides: kiwi-filesystem:btrfs -Provides: kiwi-filesystem:xfs Provides: kiwi-filesystem:ext3 Provides: kiwi-filesystem:ext4 Provides: kiwi-filesystem:squashfs +Provides: kiwi-filesystem:xfs Requires: btrfsprogs Requires: e2fsprogs -Requires: xfsprogs Requires: python3-kiwi = %{version} +Requires: xfsprogs Requires: %(echo `cat %{S:1}|grep %{_target_cpu}:%{distro}:|cut -f3- -d:`) -License: GPL-3.0+ -Group: System/Management %description -n kiwi-boot-requires Meta package for the buildservice to pull in all required packages in @@ -248,7 +258,6 @@ %package -n kiwi-man-pages Summary: KIWI - manual pages -License: GPL-3.0+ Group: System/Management %description -n kiwi-man-pages ++++++ python-kiwi.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/.bumpversion.cfg new/kiwi-9.4.0/.bumpversion.cfg --- old/kiwi-9.3.3/.bumpversion.cfg 2017-03-13 14:47:47.000000000 +0100 +++ new/kiwi-9.4.0/.bumpversion.cfg 2017-03-16 09:45:14.000000000 +0100 @@ -1,5 +1,5 @@ [bumpversion] -current_version = 9.3.3 +current_version = 9.4.0 commit = True tag = True diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/PKG-INFO new/kiwi-9.4.0/PKG-INFO --- old/kiwi-9.3.3/PKG-INFO 2017-03-13 17:00:48.000000000 +0100 +++ new/kiwi-9.4.0/PKG-INFO 2017-03-16 09:50:29.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: kiwi -Version: 9.3.3 +Version: 9.4.0 Summary: KIWI - Appliance Builder (next generation) Home-page: http://suse.github.io/kiwi Author: Marcus Schaefer Binary files old/kiwi-9.3.3/boot_arch.tgz and new/kiwi-9.4.0/boot_arch.tgz differ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/doc/build/man/kiwi.2 new/kiwi-9.4.0/doc/build/man/kiwi.2 --- old/kiwi-9.3.3/doc/build/man/kiwi.2 2017-03-13 17:00:43.000000000 +0100 +++ new/kiwi-9.4.0/doc/build/man/kiwi.2 2017-03-16 09:50:23.000000000 +0100 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "KIWI" "2" "Mar 13, 2017" "9.3.3" "kiwi" +.TH "KIWI" "2" "Mar 16, 2017" "9.4.0" "kiwi" .SH NAME kiwi \- Creating Operating System Images . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/doc/build/man/kiwi::image::info.2 new/kiwi-9.4.0/doc/build/man/kiwi::image::info.2 --- old/kiwi-9.3.3/doc/build/man/kiwi::image::info.2 2017-03-13 17:00:43.000000000 +0100 +++ new/kiwi-9.4.0/doc/build/man/kiwi::image::info.2 2017-03-16 09:50:23.000000000 +0100 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "KIWI::IMAGE::INFO" "2" "Mar 13, 2017" "9.3.3" "kiwi" +.TH "KIWI::IMAGE::INFO" "2" "Mar 16, 2017" "9.4.0" "kiwi" .SH NAME kiwi::image::info \- Provide detailed information about an image description . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/doc/build/man/kiwi::image::resize.2 new/kiwi-9.4.0/doc/build/man/kiwi::image::resize.2 --- old/kiwi-9.3.3/doc/build/man/kiwi::image::resize.2 2017-03-13 17:00:43.000000000 +0100 +++ new/kiwi-9.4.0/doc/build/man/kiwi::image::resize.2 2017-03-16 09:50:23.000000000 +0100 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "KIWI::IMAGE::RESIZE" "2" "Mar 13, 2017" "9.3.3" "kiwi" +.TH "KIWI::IMAGE::RESIZE" "2" "Mar 16, 2017" "9.4.0" "kiwi" .SH NAME kiwi::image::resize \- Resize disk images to new geometry . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/doc/build/man/kiwi::result::bundle.2 new/kiwi-9.4.0/doc/build/man/kiwi::result::bundle.2 --- old/kiwi-9.3.3/doc/build/man/kiwi::result::bundle.2 2017-03-13 17:00:43.000000000 +0100 +++ new/kiwi-9.4.0/doc/build/man/kiwi::result::bundle.2 2017-03-16 09:50:23.000000000 +0100 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "KIWI::RESULT::BUNDLE" "2" "Mar 13, 2017" "9.3.3" "kiwi" +.TH "KIWI::RESULT::BUNDLE" "2" "Mar 16, 2017" "9.4.0" "kiwi" .SH NAME kiwi::result::bundle \- Bundle build results . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/doc/build/man/kiwi::result::list.2 new/kiwi-9.4.0/doc/build/man/kiwi::result::list.2 --- old/kiwi-9.3.3/doc/build/man/kiwi::result::list.2 2017-03-13 17:00:43.000000000 +0100 +++ new/kiwi-9.4.0/doc/build/man/kiwi::result::list.2 2017-03-16 09:50:23.000000000 +0100 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "KIWI::RESULT::LIST" "2" "Mar 13, 2017" "9.3.3" "kiwi" +.TH "KIWI::RESULT::LIST" "2" "Mar 16, 2017" "9.4.0" "kiwi" .SH NAME kiwi::result::list \- List build results . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/doc/build/man/kiwi::system::build.2 new/kiwi-9.4.0/doc/build/man/kiwi::system::build.2 --- old/kiwi-9.3.3/doc/build/man/kiwi::system::build.2 2017-03-13 17:00:43.000000000 +0100 +++ new/kiwi-9.4.0/doc/build/man/kiwi::system::build.2 2017-03-16 09:50:23.000000000 +0100 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "KIWI::SYSTEM::BUILD" "2" "Mar 13, 2017" "9.3.3" "kiwi" +.TH "KIWI::SYSTEM::BUILD" "2" "Mar 16, 2017" "9.4.0" "kiwi" .SH NAME kiwi::system::build \- Build image in combined prepare and create step . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/doc/build/man/kiwi::system::create.2 new/kiwi-9.4.0/doc/build/man/kiwi::system::create.2 --- old/kiwi-9.3.3/doc/build/man/kiwi::system::create.2 2017-03-13 17:00:43.000000000 +0100 +++ new/kiwi-9.4.0/doc/build/man/kiwi::system::create.2 2017-03-16 09:50:23.000000000 +0100 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "KIWI::SYSTEM::CREATE" "2" "Mar 13, 2017" "9.3.3" "kiwi" +.TH "KIWI::SYSTEM::CREATE" "2" "Mar 16, 2017" "9.4.0" "kiwi" .SH NAME kiwi::system::create \- Create image from prepared root system . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/doc/build/man/kiwi::system::prepare.2 new/kiwi-9.4.0/doc/build/man/kiwi::system::prepare.2 --- old/kiwi-9.3.3/doc/build/man/kiwi::system::prepare.2 2017-03-13 17:00:43.000000000 +0100 +++ new/kiwi-9.4.0/doc/build/man/kiwi::system::prepare.2 2017-03-16 09:50:23.000000000 +0100 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "KIWI::SYSTEM::PREPARE" "2" "Mar 13, 2017" "9.3.3" "kiwi" +.TH "KIWI::SYSTEM::PREPARE" "2" "Mar 16, 2017" "9.4.0" "kiwi" .SH NAME kiwi::system::prepare \- Prepare image root system . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/doc/build/man/kiwi::system::update.2 new/kiwi-9.4.0/doc/build/man/kiwi::system::update.2 --- old/kiwi-9.3.3/doc/build/man/kiwi::system::update.2 2017-03-13 17:00:43.000000000 +0100 +++ new/kiwi-9.4.0/doc/build/man/kiwi::system::update.2 2017-03-16 09:50:23.000000000 +0100 @@ -1,6 +1,6 @@ .\" Man page generated from reStructuredText. . -.TH "KIWI::SYSTEM::UPDATE" "2" "Mar 13, 2017" "9.3.3" "kiwi" +.TH "KIWI::SYSTEM::UPDATE" "2" "Mar 16, 2017" "9.4.0" "kiwi" .SH NAME kiwi::system::update \- Update/Upgrade image root system . diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/doc/source/conf.py new/kiwi-9.4.0/doc/source/conf.py --- old/kiwi-9.3.3/doc/source/conf.py 2017-03-13 14:47:47.000000000 +0100 +++ new/kiwi-9.4.0/doc/source/conf.py 2017-03-16 09:45:14.000000000 +0100 @@ -92,7 +92,7 @@ # built documents. # # The short X.Y version. -version = u'9.3.3' +version = u'9.4.0' # The full version, including alpha/beta/rc tags. release = version diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/builder/container.py new/kiwi-9.4.0/kiwi/builder/container.py --- old/kiwi-9.3.3/kiwi/builder/container.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/builder/container.py 2017-03-16 09:44:58.000000000 +0100 @@ -16,6 +16,7 @@ # along with kiwi. If not, see <http://www.gnu.org/licenses/> # import platform +import os # project from kiwi.container import ContainerImage @@ -23,6 +24,9 @@ from kiwi.system.setup import SystemSetup from kiwi.logger import log from kiwi.system.result import Result +from kiwi.utils.checksum import Checksum +from kiwi.defaults import Defaults +from kiwi.exceptions import KiwiContainerBuilderError class ContainerBuilder(object): @@ -57,6 +61,31 @@ self.target_dir = target_dir self.container_config = xml_state.get_container_config() self.requested_container_type = xml_state.get_build_type_name() + self.base_image = None + self.base_image_md5 = None + + if xml_state.get_derived_from_image_uri(): + # The base image is expected to be unpacked by the kiwi + # prepare step and stored inside of the root_dir/image directory. + # In addition a md5 file of the image is expected too + self.base_image = Defaults.get_imported_root_image( + self.root_dir + ) + self.base_image_md5 = ''.join([self.base_image, '.md5']) + + if not os.path.exists(self.base_image): + raise KiwiContainerBuilderError( + 'Unpacked Base image {0} not found'.format( + self.base_image + ) + ) + if not os.path.exists(self.base_image_md5): + raise KiwiContainerBuilderError( + 'Base image MD5 sum {0} not found at'.format( + self.base_image_md5 + ) + ) + self.system_setup = SystemSetup( xml_state=xml_state, root_dir=self.root_dir ) @@ -80,13 +109,23 @@ * image="docker" """ - log.info( - 'Setting up %s container', self.requested_container_type - ) - container_setup = ContainerSetup( - self.requested_container_type, self.root_dir, self.container_config - ) - container_setup.setup() + if not self.base_image: + log.info( + 'Setting up %s container', self.requested_container_type + ) + container_setup = ContainerSetup( + self.requested_container_type, self.root_dir, + self.container_config + ) + container_setup.setup() + else: + checksum = Checksum(self.base_image) + if not checksum.matches(checksum.md5(), self.base_image_md5): + raise KiwiContainerBuilderError( + 'base image file {0} checksum validation failed'.format( + self.base_image + ) + ) log.info( '--> Creating container image' @@ -95,7 +134,7 @@ self.requested_container_type, self.root_dir, self.container_config ) container_image.create( - self.filename + self.filename, self.base_image ) self.result.add( key='container', diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/container/docker.py new/kiwi-9.4.0/kiwi/container/docker.py --- old/kiwi-9.3.3/kiwi/container/docker.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/container/docker.py 2017-03-16 09:44:58.000000000 +0100 @@ -92,11 +92,13 @@ if not self.entry_command and not self.entry_subcommand: self.entry_subcommand = ['--config.cmd=/bin/bash'] - def create(self, filename): + def create(self, filename, base_image): """ Create compressed docker system container tar archive :param string filename: archive file name + + :param string base_image: archive used as a base image """ exclude_list = [ 'image', '.profile', '.kconfig', 'boot', 'dev', 'sys', 'proc', @@ -113,12 +115,20 @@ [container_dir, self.container_tag] ) - Command.run( - ['umoci', 'init', '--layout', container_dir] - ) - Command.run( - ['umoci', 'new', '--image', container_name] - ) + if base_image: + Command.run([ + 'skopeo', 'copy', + 'docker-archive:{0}'.format(base_image), + 'oci:{0}'.format(container_name) + ]) + else: + Command.run( + ['umoci', 'init', '--layout', container_dir] + ) + Command.run( + ['umoci', 'new', '--image', container_name] + ) + Command.run( ['umoci', 'unpack', '--image', container_name, self.docker_root_dir] ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/defaults.py new/kiwi-9.4.0/kiwi/defaults.py --- old/kiwi-9.3.3/kiwi/defaults.py 2017-03-07 11:23:36.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/defaults.py 2017-03-16 09:44:58.000000000 +0100 @@ -720,6 +720,21 @@ """ return resource_filename('kiwi', filename) + @classmethod + def get_imported_root_image(self, root_dir): + """ + Returns the path of the image used to import a root during + the prepare task. This is the filename expected to be + found during the create step if derived_from attribute is + present. + + :param string root_dir: is the root directory of the current build + + :return: file name of the image + :rtype: string + """ + return os.sep.join([root_dir, 'image', 'imported_root']) + def get(self, key): """ Implements get method for profile elements diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/exceptions.py new/kiwi-9.4.0/kiwi/exceptions.py --- old/kiwi-9.3.3/kiwi/exceptions.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/exceptions.py 2017-03-16 09:44:58.000000000 +0100 @@ -752,3 +752,10 @@ Exception is raised when something fails during the root import procedure. """ + + +class KiwiContainerBuilderError(KiwiError): + """ + Exception is raised when something fails during a container image + build procedure. + """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/system/prepare.py new/kiwi-9.4.0/kiwi/system/prepare.py --- old/kiwi-9.3.3/kiwi/system/prepare.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/system/prepare.py 2017-03-16 09:44:58.000000000 +0100 @@ -67,7 +67,7 @@ root_dir, allow_existing ) root.create() - image_uri = xml_state.build_type.get_derived_from() + image_uri = xml_state.get_derived_from_image_uri() if image_uri: root_import = RootImport( root_dir, image_uri, xml_state.build_type.get_image() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/system/root_import/base.py new/kiwi-9.4.0/kiwi/system/root_import/base.py --- old/kiwi-9.3.3/kiwi/system/root_import/base.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/system/root_import/base.py 2017-03-16 09:44:58.000000000 +0100 @@ -16,9 +16,12 @@ # along with kiwi. If not, see <http://www.gnu.org/licenses/> # import os +import shutil # project -from kiwi.system.uri import Uri +from kiwi.path import Path +from kiwi.utils.checksum import Checksum +from kiwi.defaults import Defaults from kiwi.exceptions import KiwiRootImportError @@ -29,27 +32,26 @@ * :attr:`root_dir` root directory path name - * :attr:`image_file` - local image file to import - - * :attr:`tmp_root_dir` - temporary directory where image_file is extracted + * :attr:`image_uri` + Uri object to store source location """ def __init__(self, root_dir, image_uri): - uri = Uri(image_uri) - if uri.is_remote(): - raise KiwiRootImportError( - 'Only local imports are supported' - ) - else: - self.image_file = uri.translate() + try: + if image_uri.is_remote(): + raise KiwiRootImportError( + 'Only local imports are supported' + ) + + self.image_file = image_uri.translate() + if not os.path.exists(self.image_file): raise KiwiRootImportError( 'Could not stat base image file: {0}'.format(self.image_file) ) - self.root_dir = root_dir - self.post_init() + self.root_dir = root_dir + finally: + self.post_init() def post_init(self): """ @@ -66,3 +68,10 @@ Implementation in specialized root import class """ raise NotImplementedError + + def _copy_image(self, image): + image_copy = Defaults.get_imported_root_image(self.root_dir) + Path.create(os.path.dirname(image_copy)) + shutil.copy(image, image_copy) + checksum = Checksum(image_copy) + checksum.md5(''.join([image_copy, '.md5'])) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/system/root_import/docker.py new/kiwi-9.4.0/kiwi/system/root_import/docker.py --- old/kiwi-9.3.3/kiwi/system/root_import/docker.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/system/root_import/docker.py 2017-03-16 09:44:58.000000000 +0100 @@ -63,6 +63,12 @@ ) synchronizer.sync_data(options=['-a', '-H', '-X', '-A']) + # A copy of the uncompressed image and its checksum are + # kept inside the root_dir in order to ensure the later steps + # i.e. system create are atomic and don't need any third + # party archive. + self._copy_image(self.uncompressed_image) + def __del__(self): if self.oci_layout_dir: Path.wipe(self.oci_layout_dir) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/system/uri.py new/kiwi-9.4.0/kiwi/system/uri.py --- old/kiwi-9.3.3/kiwi/system/uri.py 2017-03-13 14:47:47.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/system/uri.py 2017-03-16 09:44:58.000000000 +0100 @@ -113,7 +113,7 @@ return self._suse_buildservice_path( ''.join([uri.netloc, uri.path]) ) - elif uri.scheme == 'http' or uri.scheme == 'ftp': + elif uri.scheme == 'http' or uri.scheme == 'https' or uri.scheme == 'ftp': return ''.join([uri.scheme, '://', uri.netloc, uri.path]) else: raise KiwiUriStyleUnknown( diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/utils/checksum.py new/kiwi-9.4.0/kiwi/utils/checksum.py --- old/kiwi-9.3.3/kiwi/utils/checksum.py 2017-03-07 15:11:03.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/utils/checksum.py 2017-03-16 09:44:58.000000000 +0100 @@ -48,6 +48,27 @@ self.source_filename = source_filename self.checksum_filename = None + def matches(self, checksum, filename): + """ + Compare given checksum with reference checksum stored + in the provided filename. If the checksum matches the + method returns True, or False in case it does not match + + :param string checksum: checksum string to compare + :param string filename: filename containing checksum + """ + if not os.path.exists(filename): + return False + with open(filename) as checksum_file: + checksum_from_file = checksum_file.read() + # checksum is expected to be stored in the first field + # separated by space, other information might contain + # the filename or blocklist data which is not of interest + # for the plain checksum match + if checksum_from_file.split(' ')[0] == checksum: + return True + return False + def md5(self, filename=None): """ Create md5 checksum diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/version.py new/kiwi-9.4.0/kiwi/version.py --- old/kiwi-9.3.3/kiwi/version.py 2017-03-13 16:55:55.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/version.py 2017-03-16 09:45:14.000000000 +0100 @@ -18,5 +18,5 @@ """ Global version information used in kiwi and the package """ -__version__ = '9.3.3' -__githash__ = '2b2bb847eb2383a5318dd67ad285c400114edf5b' +__version__ = '9.4.0' +__githash__ = 'd62ae5e31ef3e13d6a234e1559178c3ed2a137ec' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi/xml_state.py new/kiwi-9.4.0/kiwi/xml_state.py --- old/kiwi-9.3.3/kiwi/xml_state.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/kiwi/xml_state.py 2017-03-16 09:44:58.000000000 +0100 @@ -22,6 +22,7 @@ # project from . import xml_parse +from .system.uri import Uri from .defaults import Defaults from .exceptions import ( @@ -1474,6 +1475,21 @@ return option_list + def get_derived_from_image_uri(self): + """ + Uri object of derived image if configured + + Specific image types can be based on a master image. + This method returns the location of this image when + configured in the XML description + + :return: Instance of Uri + :rtype: object + """ + derived_image = self.build_type.get_derived_from() + if derived_image: + return Uri(derived_image) + def _used_profiles(self, profiles=None): """ return list of profiles to use. The method looks up the diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/kiwi.egg-info/PKG-INFO new/kiwi-9.4.0/kiwi.egg-info/PKG-INFO --- old/kiwi-9.3.3/kiwi.egg-info/PKG-INFO 2017-03-13 17:00:44.000000000 +0100 +++ new/kiwi-9.4.0/kiwi.egg-info/PKG-INFO 2017-03-16 09:50:24.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: kiwi -Version: 9.3.3 +Version: 9.4.0 Summary: KIWI - Appliance Builder (next generation) Home-page: http://suse.github.io/kiwi Author: Marcus Schaefer diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/package/python-kiwi-spec-template new/kiwi-9.4.0/package/python-kiwi-spec-template --- old/kiwi-9.3.3/package/python-kiwi-spec-template 2017-03-13 16:55:55.000000000 +0100 +++ new/kiwi-9.4.0/package/python-kiwi-spec-template 2017-03-15 16:57:42.000000000 +0100 @@ -19,27 +19,41 @@ %{!?python2_sitelib:%global python2_sitelib %{python_sitelib}} # translate version id to distribution name as it is used in kiwi +# generic approach %if 0%{?suse_version} %define distro %(echo `export VER=%{suse_version}; echo "suse-${VER:0:2}.${VER:2:1}"`) -# redefine for the SLES case if no sles_version exists +%endif + # SLE12: %if 0%{?suse_version} == 1315 && !0%{?is_opensuse} %define distro suse-SLES12 %endif -# Leap 42.1: -%if 0%{?suse_version} == 1315 && 0%{?is_opensuse} + +# SLE13: +%if 0%{?sle_version} == 130000 && !0%{?is_opensuse} +%define distro suse-SLES13 +%endif + +# Leap 42.1(openSUSE product based on SLE 12SP1): +%if 0%{?is_opensuse} && 0%{?sle_version} == 120100 %define distro suse-leap42.1 %endif + # Leap 42.2: -%if 0%{?suse_version} == 1316 && 0%{?is_opensuse} +%if 0%{?leap_version} == 420200 %define distro suse-leap42.2 %endif + +# Leap 42.3: +%if 0%{?leap_version} == 420300 +%define distro suse-leap42.3 +%endif + # Tumbleweed: # Current Tumbleweed version, moving target %if 0%{?suse_version} == 1330 %define distro suse-tumbleweed %endif -%endif # SLES with sles_version macro %if 0%{?sles_version} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/setup.cfg new/kiwi-9.4.0/setup.cfg --- old/kiwi-9.3.3/setup.cfg 2017-03-13 17:00:48.000000000 +0100 +++ new/kiwi-9.4.0/setup.cfg 2017-03-16 09:50:29.000000000 +0100 @@ -18,6 +18,6 @@ [egg_info] tag_build = -tag_svn_revision = 0 tag_date = 0 +tag_svn_revision = 0 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/test/unit/builder_container_test.py new/kiwi-9.4.0/test/unit/builder_container_test.py --- old/kiwi-9.3.3/test/unit/builder_container_test.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/test/unit/builder_container_test.py 2017-03-16 09:44:58.000000000 +0100 @@ -3,28 +3,36 @@ import mock import kiwi +from .test_helper import raises, patch_open + +from kiwi.system.uri import Uri from kiwi.builder.container import ContainerBuilder +from kiwi.exceptions import KiwiContainerBuilderError class TestContainerBuilder(object): @patch('platform.machine') - def setup(self, mock_machine): + @patch('os.path.exists') + def setup(self, mock_exists, mock_machine): + mock_exists.return_value = True mock_machine.return_value = 'x86_64' - xml_state = mock.Mock() + self.uri = Uri('file:///image_file.tar.xz') + self.xml_state = mock.Mock() + self.xml_state.get_derived_from_image_uri.return_value = self.uri self.container_config = { 'container_name': 'my-container', 'entry_command': ["--config.cmd='/bin/bash'"] } - xml_state.get_container_config = mock.Mock( + self.xml_state.get_container_config = mock.Mock( return_value=self.container_config ) - xml_state.get_image_version = mock.Mock( + self.xml_state.get_image_version = mock.Mock( return_value='1.2.3' ) - xml_state.get_build_type_name = mock.Mock( + self.xml_state.get_build_type_name = mock.Mock( return_value='docker' ) - xml_state.xml_data.get_name = mock.Mock( + self.xml_state.xml_data.get_name = mock.Mock( return_value='image_name' ) self.setup = mock.Mock() @@ -32,10 +40,59 @@ return_value=self.setup ) self.container = ContainerBuilder( - xml_state, 'target_dir', 'root_dir' + self.xml_state, 'target_dir', 'root_dir' ) self.container.result = mock.Mock() + @patch('os.path.exists') + def test_init_derived(self, mock_exists): + mock_exists.return_value = True + builder = ContainerBuilder( + self.xml_state, 'target_dir', 'root_dir' + ) + assert builder.base_image == 'root_dir/image/imported_root' + + @patch('os.path.exists') + @raises(KiwiContainerBuilderError) + def test_init_derived_base_image_not_existing(self, mock_exists): + mock_exists.return_value = False + ContainerBuilder( + self.xml_state, 'target_dir', 'root_dir' + ) + + @patch('os.path.exists') + @raises(KiwiContainerBuilderError) + def test_init_derived_base_image_md5_not_existing(self, mock_exists): + exists_results = [False, True] + + def side_effect(self): + return exists_results.pop() + + mock_exists.side_effect = side_effect + ContainerBuilder( + self.xml_state, 'target_dir', 'root_dir' + ) + + @patch('kiwi.builder.container.Checksum') + @patch('kiwi.builder.container.ContainerImage') + @patch('os.path.exists') + @raises(KiwiContainerBuilderError) + def test_create_derived_checksum_match_failed( + self, mock_exists, mock_image, mock_checksum + ): + mock_exists.return_value = True + container = ContainerBuilder( + self.xml_state, 'target_dir', 'root_dir' + ) + container.result = mock.Mock() + + checksum = mock.Mock() + checksum.matches = mock.Mock( + return_value=False + ) + mock_checksum.return_value = checksum + container.create() + @patch('kiwi.builder.container.ContainerSetup') @patch('kiwi.builder.container.ContainerImage') def test_create(self, mock_image, mock_setup): @@ -45,6 +102,7 @@ mock_image.return_value = container_image self.setup.export_rpm_package_verification.return_value = '.verified' self.setup.export_rpm_package_list.return_value = '.packages' + self.container.base_image = None self.container.create() mock_setup.assert_called_once_with( 'docker', 'root_dir', self.container_config @@ -54,7 +112,7 @@ 'docker', 'root_dir', self.container_config ) container_image.create.assert_called_once_with( - 'target_dir/image_name.x86_64-1.2.3.docker.tar.xz' + 'target_dir/image_name.x86_64-1.2.3.docker.tar.xz', None ) assert self.container.result.add.call_args_list == [ call( @@ -85,3 +143,109 @@ self.setup.export_rpm_package_list.assert_called_once_with( 'target_dir' ) + + @patch('kiwi.builder.container.Checksum') + @patch('kiwi.builder.container.ContainerImage') + @patch('os.path.exists') + def test_create_derived(self, mock_exists, mock_image, mock_checksum): + mock_exists.return_value = True + container = ContainerBuilder( + self.xml_state, 'target_dir', 'root_dir' + ) + container.result = mock.Mock() + + checksum = mock.Mock() + checksum.md5 = mock.Mock( + return_value='checksumvalue' + ) + mock_checksum.return_value = checksum + + container_image = mock.Mock() + mock_image.return_value = container_image + self.setup.export_rpm_package_verification.return_value = '.verified' + self.setup.export_rpm_package_list.return_value = '.packages' + + container.create() + + mock_checksum.assert_called_once_with('root_dir/image/imported_root') + checksum.matches.assert_called_once_with( + 'checksumvalue', 'root_dir/image/imported_root.md5' + ) + + mock_image.assert_called_once_with( + 'docker', 'root_dir', self.container_config + ) + container_image.create.assert_called_once_with( + 'target_dir/image_name.x86_64-1.2.3.docker.tar.xz', + 'root_dir/image/imported_root' + ) + assert container.result.add.call_args_list == [ + call( + key='container', + filename='target_dir/image_name.x86_64-1.2.3.docker.tar.xz', + use_for_bundle=True, + compress=False, + shasum=True + ), + call( + key='image_packages', + filename='.packages', + use_for_bundle=True, + compress=False, + shasum=False + ), + call( + key='image_verified', + filename='.verified', + use_for_bundle=True, + compress=False, + shasum=False + ) + ] + self.setup.export_rpm_package_verification.assert_called_once_with( + 'target_dir' + ) + self.setup.export_rpm_package_list.assert_called_once_with( + 'target_dir' + ) + + @patch_open + @patch('kiwi.builder.container.Checksum') + @raises(KiwiContainerBuilderError) + def test_create_derived_with_different_md5(self, mock_md5, mock_open): + container = ContainerBuilder( + self.xml_state, 'target_dir', 'root_dir' + ) + + md5 = mock.Mock() + md5.md5.return_value = 'diffchecksumvalue' + mock_md5.return_value = md5 + + context_manager_mock = mock.Mock() + file_mock = mock.Mock() + file_mock.read.return_value = 'checksumvalue and someotherstuff\n' + enter_mock = mock.Mock() + exit_mock = mock.Mock() + enter_mock.return_value = file_mock + setattr(context_manager_mock, '__enter__', enter_mock) + setattr(context_manager_mock, '__exit__', exit_mock) + mock_open.return_value = context_manager_mock + + container.create() + + @patch_open + @patch('kiwi.builder.container.Checksum') + @raises(Exception) + def test_create_derived_fail_open(self, mock_md5, mock_open): + container = ContainerBuilder( + self.xml_state, 'target_dir', 'root_dir' + ) + + context_manager_mock = mock.Mock() + enter_mock = mock.Mock(side_effect=Exception('open failed!')) + exit_mock = mock.Mock() + setattr(context_manager_mock, '__enter__', enter_mock) + setattr(context_manager_mock, '__exit__', exit_mock) + mock_open.return_value = context_manager_mock + + container.create() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/test/unit/container_image_docker_test.py new/kiwi-9.4.0/test/unit/container_image_docker_test.py --- old/kiwi-9.3.3/test/unit/container_image_docker_test.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/test/unit/container_image_docker_test.py 2017-03-16 09:44:58.000000000 +0100 @@ -51,10 +51,9 @@ @patch('kiwi.container.docker.Path.wipe') def test_del(self, mock_wipe): - docker = ContainerImageDocker('root_dir') - docker.docker_dir = 'dir_a' - docker.docker_root_dir = 'dir_b' - docker.__del__() + self.docker.docker_dir = 'dir_a' + self.docker.docker_root_dir = 'dir_b' + self.docker.__del__() assert mock_wipe.call_args_list == [ call('dir_a'), call('dir_b') ] @@ -64,9 +63,12 @@ @patch('kiwi.container.docker.DataSync') @patch('kiwi.container.docker.mkdtemp') @patch('kiwi.container.docker.Path.wipe') + @patch('kiwi.container.docker.Defaults.get_shared_cache_location') def test_create( - self, mock_wipe, mock_mkdtemp, mock_sync, mock_command, mock_compress + self, mock_cache, mock_wipe, mock_mkdtemp, + mock_sync, mock_command, mock_compress ): + mock_cache.return_value = 'var/cache/kiwi' compressor = mock.Mock() mock_compress.return_value = compressor docker_root = mock.Mock() @@ -78,7 +80,7 @@ mock_mkdtemp.side_effect = call_mkdtemp - self.docker.create('result.tar.xz') + self.docker.create('result.tar.xz', None) mock_wipe.assert_called_once_with('result.tar') @@ -93,6 +95,70 @@ ]), call([ 'umoci', 'unpack', '--image', + 'kiwi_docker_dir/umoci_layout:latest', 'kiwi_docker_root_dir' + ]), + call([ + 'umoci', 'repack', '--image', + 'kiwi_docker_dir/umoci_layout:latest', 'kiwi_docker_root_dir' + ]), + call([ + 'umoci', 'config', '--config.cmd=/bin/bash', '--image', + 'kiwi_docker_dir/umoci_layout:latest', '--tag', 'latest' + ]), + call([ + 'umoci', 'gc', '--layout', 'kiwi_docker_dir/umoci_layout' + ]), + call([ + 'skopeo', 'copy', 'oci:kiwi_docker_dir/umoci_layout:latest', + 'docker-archive:result.tar:foo/bar:latest' + ]) + ] + mock_sync.assert_called_once_with( + 'root_dir/', 'kiwi_docker_root_dir/rootfs' + ) + docker_root.sync_data.assert_called_once_with( + exclude=[ + 'image', '.profile', '.kconfig', 'boot', 'dev', 'sys', 'proc', + 'var/cache/kiwi' + ], + options=['-a', '-H', '-X', '-A'] + ) + mock_compress.assert_called_once_with('result.tar') + compressor.xz.assert_called_once_with() + + @patch('kiwi.container.docker.Compress') + @patch('kiwi.container.docker.Command.run') + @patch('kiwi.container.docker.DataSync') + @patch('kiwi.container.docker.mkdtemp') + @patch('kiwi.container.docker.Path.wipe') + @patch('kiwi.container.docker.Defaults.get_shared_cache_location') + def test_create_derived( + self, mock_cache, mock_wipe, mock_mkdtemp, + mock_sync, mock_command, mock_compress + ): + mock_cache.return_value = 'var/cache/kiwi' + compressor = mock.Mock() + mock_compress.return_value = compressor + docker_root = mock.Mock() + mock_sync.return_value = docker_root + tmpdirs = ['kiwi_docker_root_dir', 'kiwi_docker_dir'] + + def call_mkdtemp(prefix): + return tmpdirs.pop() + + mock_mkdtemp.side_effect = call_mkdtemp + + self.docker.create('result.tar.xz', 'root_dir/image/image_file') + + mock_wipe.assert_called_once_with('result.tar') + + assert mock_command.call_args_list == [ + call([ + 'skopeo', 'copy', 'docker-archive:root_dir/image/image_file', + 'oci:kiwi_docker_dir/umoci_layout:latest' + ]), + call([ + 'umoci', 'unpack', '--image', 'kiwi_docker_dir/umoci_layout:latest', 'kiwi_docker_root_dir' ]), call([ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/test/unit/system_prepare_test.py new/kiwi-9.4.0/test/unit/system_prepare_test.py --- old/kiwi-9.3.3/test/unit/system_prepare_test.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/test/unit/system_prepare_test.py 2017-03-16 09:44:58.000000000 +0100 @@ -79,6 +79,11 @@ state = XMLState( xml, profiles=['vmxFlavour'], build_type='docker' ) + uri = mock.Mock() + get_derived_from_image_uri = mock.Mock( + return_value=uri + ) + state.get_derived_from_image_uri = get_derived_from_image_uri SystemPrepare( xml_state=state, root_dir='root_dir', ) @@ -87,7 +92,7 @@ ) root_init.create.assert_called_once_with() mock_root_import.assert_called_once_with( - 'root_dir', 'file:///image.tar.xz', + 'root_dir', uri, state.build_type.get_image() ) root_import.sync_data.assert_called_once_with() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/test/unit/system_root_import_base_test.py new/kiwi-9.4.0/test/unit/system_root_import_base_test.py --- old/kiwi-9.3.3/test/unit/system_root_import_base_test.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/test/unit/system_root_import_base_test.py 2017-03-16 09:44:58.000000000 +0100 @@ -2,6 +2,7 @@ from .test_helper import raises +from kiwi.system.uri import Uri from kiwi.system.root_import.base import RootImportBase from kiwi.exceptions import KiwiRootImportError @@ -10,23 +11,23 @@ @patch('os.path.exists') def test_init(self, mock_path): mock_path.return_value = True - RootImportBase('root_dir', 'file:///image.tar.xz') + RootImportBase('root_dir', Uri('file:///image.tar.xz')) mock_path.assert_called_once_with('/image.tar.xz') @raises(KiwiRootImportError) def test_init_remote_uri(self): - RootImportBase('root_dir', 'http://example.com/image.tar.xz') + RootImportBase('root_dir', Uri('http://example.com/image.tar.xz')) @patch('os.path.exists') @raises(KiwiRootImportError) def test_init_non_existing(self, mock_path): mock_path.return_value = False - RootImportBase('root_dir', 'file:///image.tar.xz') + RootImportBase('root_dir', Uri('file:///image.tar.xz')) mock_path.assert_called_once_with('/image.tar.xz') @raises(NotImplementedError) @patch('os.path.exists') def test_data_sync(self, mock_path): mock_path.return_value = True - root_import = RootImportBase('root_dir', 'file:///image.tar.xz') + root_import = RootImportBase('root_dir', Uri('file:///image.tar.xz')) root_import.sync_data() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/test/unit/system_root_import_docker_test.py new/kiwi-9.4.0/test/unit/system_root_import_docker_test.py --- old/kiwi-9.3.3/test/unit/system_root_import_docker_test.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/test/unit/system_root_import_docker_test.py 2017-03-16 09:44:58.000000000 +0100 @@ -2,7 +2,11 @@ from mock import patch from mock import call +from .test_helper import raises + +from kiwi.system.uri import Uri from kiwi.system.root_import.docker import RootImportDocker +from kiwi.exceptions import KiwiRootImportError class TestRootImportDocker(object): @@ -10,16 +14,28 @@ def setup(self, mock_path): mock_path.return_value = True self.docker_import = RootImportDocker( - 'root_dir', 'file:///image.tar.xz' + 'root_dir', Uri('file:///image.tar.xz') ) assert self.docker_import.image_file == '/image.tar.xz' + @patch('os.path.exists') + @raises(KiwiRootImportError) + def test_failed_init(self, mock_path): + mock_path.return_value = False + RootImportDocker( + 'root_dir', Uri('file:///image.tar.xz') + ) + + @patch('kiwi.system.root_import.base.shutil.copy') + @patch('kiwi.system.root_import.base.Checksum') + @patch('kiwi.system.root_import.base.Path.create') @patch('kiwi.system.root_import.docker.Compress') @patch('kiwi.system.root_import.docker.Command.run') @patch('kiwi.system.root_import.docker.DataSync') @patch('kiwi.system.root_import.docker.mkdtemp') def test_sync_data( - self, mock_mkdtemp, mock_sync, mock_run, mock_compress + self, mock_mkdtemp, mock_sync, mock_run, + mock_compress, mock_path, mock_md5, mock_copy ): uncompress = mock.Mock() uncompress.uncompressed_filename = 'tmp_uncompressed' @@ -35,6 +51,9 @@ sync = mock.Mock() mock_sync.return_value = sync + md5 = mock.Mock() + mock_md5.return_value = mock.Mock() + self.docker_import.sync_data() mock_compress.assert_called_once_with('/image.tar.xz') @@ -57,6 +76,12 @@ sync.sync_data.assert_called_once_with( options=['-a', '-H', '-X', '-A'] ) + mock_md5.assert_called_once_with('root_dir/image/imported_root') + md5.md5.called_once_with('root_dir/image/imported_root.md5') + mock_copy.assert_called_once_with( + 'tmp_uncompressed', 'root_dir/image/imported_root' + ) + mock_path.assert_called_once_with('root_dir/image') @patch('kiwi.system.root_import.docker.Path.wipe') def test_del(self, mock_path): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/test/unit/system_uri_test.py new/kiwi-9.4.0/test/unit/system_uri_test.py --- old/kiwi-9.3.3/test/unit/system_uri_test.py 2017-03-07 15:11:03.000000000 +0100 +++ new/kiwi-9.4.0/test/unit/system_uri_test.py 2017-03-16 09:44:58.000000000 +0100 @@ -101,6 +101,10 @@ uri = Uri('http://example.com/foo', 'rpm-md') assert uri.translate() == 'http://example.com/foo' + def test_translate_https_path(self): + uri = Uri('https://example.com/foo', 'rpm-md') + assert uri.translate() == 'https://example.com/foo' + def test_translate_ftp_path(self): uri = Uri('ftp://example.com/foo', 'rpm-md') assert uri.translate() == 'ftp://example.com/foo' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/test/unit/utils_checksum_test.py new/kiwi-9.4.0/test/unit/utils_checksum_test.py --- old/kiwi-9.3.3/test/unit/utils_checksum_test.py 2017-03-07 15:11:03.000000000 +0100 +++ new/kiwi-9.4.0/test/unit/utils_checksum_test.py 2017-03-16 09:44:58.000000000 +0100 @@ -35,6 +35,22 @@ def test_checksum_file_not_found(self): Checksum('some-file') + @patch('os.path.exists') + def test_matches_checksum_file_does_not_exist(self, mock_exists): + mock_exists.return_value = False + assert self.checksum.matches('sum', 'some-file') is False + + @patch('os.path.exists') + @patch_open + def test_matches(self, mock_open, mock_exists): + mock_exists.return_value = True + mock_open.return_value = self.context_manager_mock + self.file_mock.read.side_effect = None + self.file_mock.read.return_value = 'sum' + assert self.checksum.matches('sum', 'some-file') is True + mock_open.assert_called_once_with('some-file') + assert self.checksum.matches('foo', 'some-file') is False + @patch('kiwi.path.Path.which') @patch('kiwi.utils.checksum.Compress') @patch('hashlib.md5') diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/kiwi-9.3.3/test/unit/xml_state_test.py new/kiwi-9.4.0/test/unit/xml_state_test.py --- old/kiwi-9.3.3/test/unit/xml_state_test.py 2017-03-13 16:49:00.000000000 +0100 +++ new/kiwi-9.4.0/test/unit/xml_state_test.py 2017-03-16 09:44:58.000000000 +0100 @@ -576,3 +576,9 @@ def test_get_spare_part(self): assert self.state.get_build_type_spare_part_size() == 200 + + def test_get_derived_from_image_uri(self): + description = XMLDescription('../data/example_config.xml') + xml_data = description.load() + state = XMLState(xml_data, ['vmxFlavour'], 'docker') + assert state.get_derived_from_image_uri().translate() == '/image.tar.xz'