Package: sbuild
Version: 0.73.0-4
Severity: wishlist

The attached patch is a proof of concept for a docker chroot backend
for sbuild. It contains some hardcoded crap in the setup phase, but
that's about it (docker images generally have no build-essential, so
that needs to be installed; not sure about user, group, and sbuild
dir that seems weird).

-- System Information:
Debian Release: buster/sid
  APT prefers unstable
  APT policy: (900, 'unstable'), (900, 'testing'), (500, 'unstable-debug'), 
(500, 'buildd-unstable'), (100, 'experimental'), (1, 'experimental-debug')
Architecture: amd64 (x86_64)
Foreign Architectures: i386

Kernel: Linux 4.11.0-1-amd64 (SMP w/4 CPU cores)
Locale: LANG=en_IE.UTF-8, LC_CTYPE=en_IE.UTF-8 (charmap=UTF-8), 
LANGUAGE=en_IE.UTF-8 (charmap=UTF-8)
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)

Versions of packages sbuild depends on:
ii  adduser         3.115
ii  libsbuild-perl  0.73.0-4
ii  perl            5.24.1-5

Versions of packages sbuild recommends:
pn  autopkgtest  <none>
ii  debootstrap  1.0.90
ii  schroot      1.6.10-4

Versions of packages sbuild suggests:
ii  deborphan  1.7.28.8-0.3+b1
ii  kmod       24-1
ii  wget       1.19.1-4

-- Configuration Files:
/etc/sbuild/sbuild.conf changed [not included]

-- no debconf information

-- 
Debian Developer - deb.li/jak | jak-linux.org - free software dev
                  |  Ubuntu Core Developer |
When replying, only quote what is necessary, and write each reply
directly below the part(s) it pertains to ('inline').  Thank you.
diff --git a/Sbuild/Build.pm b/Sbuild.b/Build.pm
index b8a4b40..26b124b 100644
--- a/Sbuild/Build.pm
+++ b/Sbuild.b/Build.pm
@@ -52,6 +52,7 @@ use Sbuild::Base;
 use Sbuild::ChrootInfoSchroot;
 use Sbuild::ChrootInfoSudo;
 use Sbuild::ChrootInfoAutopkgtest;
+use Sbuild::ChrootInfoDocker;
 use Sbuild::ChrootRoot;
 use Sbuild::Sysconfig qw($version $release_date);
 use Sbuild::Sysconfig;
@@ -419,6 +420,8 @@ sub run_chroot_session {
 	    $chroot_info = Sbuild::ChrootInfoSchroot->new($self->get('Config'));
 	} elsif ($self->get_conf('CHROOT_MODE') eq 'autopkgtest') {
 	    $chroot_info = Sbuild::ChrootInfoAutopkgtest->new($self->get('Config'));
+	} elsif ($self->get_conf('CHROOT_MODE') eq 'docker') {
+	    $chroot_info = Sbuild::ChrootInfoDocker->new($self->get('Config'));
 	} else {
 	    $chroot_info = Sbuild::ChrootInfoSudo->new($self->get('Config'));
 	}
diff --git a/Sbuild.b/ChrootDocker.pm b/Sbuild.b/ChrootDocker.pm
new file mode 100644
index 0000000..9889980
--- /dev/null
+++ b/Sbuild.b/ChrootDocker.pm
@@ -0,0 +1,157 @@
+#
+# Chroot.pm: chroot library for sbuild
+# Copyright (C) 2005      Ryan Murray <[email protected]>
+# Copyright (C) 2005-2008 Roger Leigh <[email protected]>
+# Copyright (C) 2008      Simon McVittie <[email protected]>
+# Copyright (C) 2017      Julian Andres Klode <[email protected]> (docker)
+#
+# 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, either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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
+# 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
+# <http://www.gnu.org/licenses/>.
+#
+#######################################################################
+
+package Sbuild::ChrootDocker;
+
+use strict;
+use warnings;
+
+use POSIX qw(setsid);
+use Sbuild qw(shellescape);
+
+BEGIN {
+    use Exporter ();
+    use Sbuild::Chroot;
+    our (@ISA, @EXPORT);
+
+    @ISA = qw(Exporter Sbuild::Chroot);
+
+    @EXPORT = qw();
+}
+
+sub new {
+    my $class = shift;
+    my $conf = shift;
+    my $chroot_id = shift;
+
+    my $self = $class->SUPER::new($conf, $chroot_id);
+    bless($self, $class);
+
+    return $self;
+}
+
+sub begin_session {
+    my $self = shift;
+    my $chroot = $self->get('Chroot ID');
+    
+    my $session=readpipe("docker create --rm $chroot sleep 999999999999");
+    chomp($session);
+    if ($?) {
+	print STDERR "Chroot setup failed\n";
+	return 0;
+    }
+    readpipe("docker start $session");
+    if ($?) {
+	print STDERR "Chroot setup failed\n";
+	return 0;
+    }
+    readpipe("docker exec -it $session mkdir /build /var/lib/sbuild");
+    if ($?) {
+	print STDERR "Chroot setup failed\n";
+	return 0;
+    }
+    readpipe("docker exec -it $session adduser --gecos \"\" --disabled-login jak");
+    if ($?) {
+	print STDERR "Chroot setup failed\n";
+	return 0;
+    }
+    readpipe("docker exec -it $session addgroup sbuild");
+    if ($?) {
+	print STDERR "Chroot setup failed\n";
+	return 0;
+    }
+    system("docker exec -it $session sed -i s#deb.debian.org#172.17.0.1:3142# /etc/apt/sources.list");
+    system("docker exec -it $session apt-get update");
+    system("docker exec -it $session apt-get -y install build-essential");
+
+    $self->set('Session ID', $session);
+    $self->set('Session Purged', 1);
+    $self->set('Location', '/');
+
+    return 0 if !$self->_setup_options();
+
+    return 1;
+}
+
+sub end_session {
+    my $self = shift;
+	my $session = $self->get('Session ID');
+    return if $session eq "";
+    
+    readpipe("docker kill $session");
+    if ($?) {
+	print STDERR "Chroot setup failed\n";
+	return 0;
+    }
+    
+    return 1;
+}
+
+sub get_command_internal {
+    my $self = shift;
+    my $options = shift;
+    my $session = $self->get('Session ID');
+
+    # Command to run. If I have a string, use it. Otherwise use the list-ref
+    my $command = $options->{'INTCOMMAND_STR'} // $options->{'INTCOMMAND'};
+
+    my $user = $options->{'USER'};          # User to run command under
+    my $dir;                                # Directory to use (optional)
+    $dir = $self->get('Defaults')->{'DIR'} if
+	(defined($self->get('Defaults')) &&
+	 defined($self->get('Defaults')->{'DIR'}));
+    $dir = $options->{'DIR'} if
+	defined($options->{'DIR'}) && $options->{'DIR'};
+
+    if (!defined $user || $user eq "") {
+	$user = $self->get_conf('USERNAME');
+    }
+
+    my @cmdline = ("docker", "exec", "-i", $session);
+
+    if ($user ne "root") {
+	push @cmdline, "/sbin/runuser", '-u', $user, '--';
+    }
+
+    if (defined($dir)) {
+	my $shelldir = shellescape $dir;
+	push @cmdline, 'sh', '-c', "cd $shelldir && exec \"\$@\"", 'exec';
+    } else {
+	$dir = '/';
+    }
+
+    if (ref $command) {
+        push @cmdline, @$command;
+    } else {
+        push @cmdline, ('/bin/sh', '-c', $command);
+        $command = [split(/\s+/, $command)];
+    }
+
+    $options->{'USER'} = $user;
+    $options->{'COMMAND'} = $command;
+    $options->{'EXPCOMMAND'} = \@cmdline;
+    $options->{'CHDIR'} = undef;
+    $options->{'DIR'} = $dir;
+}
+
+1;
diff --git a/Sbuild.b/ChrootInfoDocker.pm b/Sbuild.b/ChrootInfoDocker.pm
new file mode 100644
index 0000000..8cbb40e
--- /dev/null
+++ b/Sbuild.b/ChrootInfoDocker.pm
@@ -0,0 +1,76 @@
+#
+# ChrootInfo.pm: chroot utility library for sbuild
+# Copyright © 2005-2009 Roger Leigh <[email protected]>
+#
+# 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, either version 2 of the License, or
+# (at your option) any later version.
+#
+# 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
+# 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
+# <http://www.gnu.org/licenses/>.
+#
+#######################################################################
+
+package Sbuild::ChrootInfoDocker;
+
+use Sbuild::ChrootInfo;
+use Sbuild::ChrootDocker;
+
+use strict;
+use warnings;
+
+BEGIN {
+    use Exporter ();
+    our (@ISA, @EXPORT);
+
+    @ISA = qw(Exporter Sbuild::ChrootInfo);
+
+    @EXPORT = qw();
+}
+
+sub new {
+    my $class = shift;
+    my $conf = shift;
+
+    my $self = $class->SUPER::new($conf);
+    bless($self, $class);
+
+    return $self;
+}
+
+sub get_info {
+    my %tmp = ('Namespace' => '',
+	       'Name' => '',
+	       'Priority' => 0,
+	       'Location' => '',
+	       'Session Purged' => 0);
+	return \%tmp;
+}
+
+sub get_info_all {
+    my $self = shift;
+
+    my $chroots = {};
+
+    $self->set('Chroots', $chroots);
+}
+
+sub _create {
+    my $self = shift;
+    my $chroot_id = shift;
+
+    my $chroot = undef;
+
+    $chroot = Sbuild::ChrootDocker->new($self->get('Config'), $chroot_id);
+
+    return $chroot;
+}
+
+1;
diff --git a/Sbuild/Conf.pm b/Sbuild.b/Conf.pm
index b70f721..0de79e3 100644
--- a/Sbuild/Conf.pm
+++ b/Sbuild.b/Conf.pm
@@ -654,7 +654,7 @@ sub setup ($) {
 
 		die "Bad chroot mode \'" . $conf->get('CHROOT_MODE') . "\'"
 		    if !isin($conf->get('CHROOT_MODE'),
-			     qw(schroot sudo autopkgtest));
+			     qw(schroot sudo autopkgtest docker));
 	    },
 	    DEFAULT => 'schroot',
 	    HELP => 'Mechanism to use for chroot virtualisation.  Possible value are "schroot" (default), "sudo" and "autopkgtest".',
diff --git a/Sbuild/Utility.pm b/Sbuild.b/Utility.pm
index 6e367e6..65bf38f 100644
--- a/Sbuild/Utility.pm
+++ b/Sbuild.b/Utility.pm
@@ -21,6 +21,7 @@
 # Import default modules into main
 package main;
 use Sbuild qw($devnull);
+use Sbuild::ChrootInfoDocker;
 use Sbuild::ChrootInfoSchroot;
 use Sbuild::ChrootInfoSudo;
 use Sbuild::Sysconfig;
@@ -90,6 +91,8 @@ sub setup ($$$) {
 	$chroot_info = Sbuild::ChrootInfoSchroot->new($conf);
     } elsif ($conf->get('CHROOT_MODE') eq 'autopkgtest') {
 	$chroot_info = Sbuild::ChrootInfoAutopkgtest->new($conf);
+    } elsif ($conf->get('CHROOT_MODE') eq 'docker') {
+	$chroot_info = Sbuild::ChrootInfoDocker->new($conf);
     } else {
 	$chroot_info = Sbuild::ChrootInfoSudo->new($conf);
     }

Reply via email to