1
0
mirror of https://github.com/pgbackrest/pgbackrest.git synced 2025-06-16 23:47:38 +02:00
Files
pgbackrest/test/lib/pgBackRestTest/Docker/ContainerTest.pm
David Steele eaa981c5aa Added execution cache for document generation.
Added an execution cache so that documentation can be generated without setting up the full container environment. This is useful for packaging, keeps the documentation consistent for a release, and speeds up generation when no changes are made in the execution list.
2016-06-02 09:32:56 -04:00

502 lines
19 KiB
Perl
Executable File

####################################################################################################################################
# ContainerTest.pm - Build docker containers for testing and documentation
####################################################################################################################################
package pgBackRestTest::Docker::ContainerTest;
####################################################################################################################################
# Perl includes
####################################################################################################################################
use strict;
use warnings FATAL => qw(all);
use Carp qw(confess longmess);
use Cwd qw(abs_path);
use Exporter qw(import);
our @EXPORT = qw();
use File::Basename qw(dirname);
use Getopt::Long qw(GetOptions);
use Scalar::Util qw(blessed);
use pgBackRest::Common::Ini;
use pgBackRest::Common::Log;
use pgBackRest::Common::String;
use pgBackRest::FileCommon;
use pgBackRestTest::Common::ExecuteTest;
use pgBackRestTest::Common::VmTest;
use constant TEST_GROUP => 'admin';
use constant TEST_GROUP_ID => 1000;
use constant TEST_USER => 'vagrant';
use constant TEST_USER_ID => TEST_GROUP_ID;
use constant POSTGRES_GROUP => 'postgres';
use constant POSTGRES_GROUP_ID => 5000;
use constant POSTGRES_USER => POSTGRES_GROUP;
use constant POSTGRES_USER_ID => POSTGRES_GROUP_ID;
use constant BACKREST_GROUP => POSTGRES_GROUP;
use constant BACKREST_GROUP_ID => POSTGRES_GROUP_ID;
use constant BACKREST_USER => 'backrest';
use constant BACKREST_USER_ID => 5001;
####################################################################################################################################
# User/group creation
####################################################################################################################################
sub groupCreate
{
my $strOS = shift;
my $strName = shift;
my $iId = shift;
return "RUN groupadd -g${iId} ${strName}";
}
sub userCreate
{
my $strOS = shift;
my $strName = shift;
my $iId = shift;
my $strGroup = shift;
my $oVm = vmGet();
if ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_RHEL)
{
return "RUN adduser -g${strGroup} -u${iId} -n ${strName}";
}
elsif ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_DEBIAN)
{
return "RUN adduser --uid=${iId} --ingroup=${strGroup} --disabled-password --gecos \"\" ${strName}";
}
confess &log(ERROR, "unable to create user for os '${strOS}'");
}
sub postgresGroupCreate
{
my $strOS = shift;
return "# Create PostgreSQL group\n" .
groupCreate($strOS, POSTGRES_GROUP, POSTGRES_GROUP_ID);
}
sub postgresUserCreate
{
my $strOS = shift;
return "# Create PostgreSQL user\n" .
userCreate($strOS, POSTGRES_USER, POSTGRES_USER_ID, POSTGRES_GROUP);
}
sub backrestUserCreate
{
my $strOS = shift;
return "# Create BackRest group\n" .
userCreate($strOS, BACKREST_USER, BACKREST_USER_ID, BACKREST_GROUP);
}
####################################################################################################################################
# Create configuration file
####################################################################################################################################
sub backrestConfigCreate
{
my $strOS = shift;
my $strUser = shift;
my $strGroup = shift;
return "# Create pgbackrest.conf\n" .
"RUN touch /etc/pgbackrest.conf\n" .
"RUN chmod 640 /etc/pgbackrest.conf\n" .
"RUN chown ${strUser}:${strGroup} /etc/pgbackrest.conf";
}
####################################################################################################################################
# Write the Docker container
####################################################################################################################################
sub containerWrite
{
my $strTempPath = shift;
my $strImageName = shift;
my $strImage = shift;
my $bForce = shift;
# Write the image
fileStringWrite("${strTempPath}/${strImageName}", trim($strImage) . "\n", false);
executeTest('docker build' . (defined($bForce) && $bForce ? ' --no-cache' : '') .
" -f ${strTempPath}/${strImageName} -t backrest/${strImageName} ${strTempPath}",
{bSuppressStdErr => true});
}
####################################################################################################################################
# Setup SSH
####################################################################################################################################
sub sshSetup
{
my $strOS = shift;
my $strUser = shift;
my $strGroup = shift;
return
"# Setup SSH\n" .
"RUN mkdir /home/${strUser}/.ssh\n" .
"COPY id_rsa /home/${strUser}/.ssh/id_rsa\n" .
"COPY id_rsa.pub /home/${strUser}/.ssh/authorized_keys\n" .
"RUN chown -R ${strUser}:${strGroup} /home/${strUser}/.ssh\n" .
"RUN chmod 700 /home/${strUser}/.ssh\n" .
"RUN echo 'Host *' > /home/${strUser}/.ssh/config\n" .
"RUN echo ' StrictHostKeyChecking no' >> /home/${strUser}/.ssh/config\n" .
"RUN echo ' LogLevel quiet' >> /home/${strUser}/.ssh/config\n" .
"RUN echo ' ControlMaster auto' >> /home/${strUser}/.ssh/config\n" .
"RUN echo ' ControlPath /tmp/\%r\@\%h:\%p' >> /home/${strUser}/.ssh/config\n" .
"RUN echo ' ControlPersist 30' >> /home/${strUser}/.ssh/config";
}
####################################################################################################################################
# Repo Setup
####################################################################################################################################
sub repoSetup
{
my $strOS = shift;
my $strUser = shift;
my $strGroup = shift;
return "# Setup repository\n" .
"RUN mkdir /var/lib/pgbackrest\n" .
"RUN chown -R ${strUser}:${strGroup} /var/lib/pgbackrest\n" .
"RUN chmod 750 /var/lib/pgbackrest";
}
####################################################################################################################################
# Install Perl packages
####################################################################################################################################
sub perlInstall
{
my $strOS = shift;
my $strImage =
"# Install Perl packages\n";
if ($strOS eq VM_CO6)
{
return $strImage .
"RUN yum -y install perl perl-Time-HiRes perl-parent perl-JSON perl-Digest-SHA perl-DBD-Pg";
}
elsif ($strOS eq VM_CO7)
{
return $strImage .
"RUN yum -y install perl perl-Thread-Queue perl-JSON-PP perl-Digest-SHA perl-DBD-Pg";
}
elsif ($strOS eq VM_U12 || $strOS eq VM_U14)
{
return $strImage .
"RUN apt-get -y install libdbd-pg-perl libdbi-perl libnet-daemon-perl libplrpc-perl";
}
elsif ($strOS eq VM_U16 || $strOS eq VM_D8)
{
return $strImage .
"RUN apt-get -y install libdbd-pg-perl libdbi-perl";
}
confess &log(ERROR, "unable to install perl for os '${strOS}'");
}
####################################################################################################################################
# Build containers
####################################################################################################################################
sub containerBuild
{
my $strVm = shift;
my $bVmForce = shift;
# Create temp path
my $strTempPath = dirname(abs_path($0)) . '/.vagrant/docker';
filePathCreate($strTempPath, '0770', true, true);
# Create SSH key (if it does not already exist)
if (-e "${strTempPath}/id_rsa")
{
&log(INFO, "SSH key already exists");
}
else
{
&log(INFO, "Building SSH keys...");
executeTest("ssh-keygen -f ${strTempPath}/id_rsa -t rsa -b 1024 -N ''", {bSuppressStdErr => true});
}
my $oVm = vmGet();
foreach my $strOS (sort(keys(%$oVm)))
{
if ($strVm ne 'all' && $strVm ne $strOS)
{
next;
}
my $oOS = $$oVm{$strOS};
my $strImage;
my $strImageName;
# Base image
###########################################################################################################################
$strImageName = "${strOS}-base";
&log(INFO, "Building ${strImageName} image...");
$strImage = "# Base Container\nFROM " . $$oVm{$strOS}{&VM_IMAGE};
# Install SSH
$strImage .= "\n\n# Install SSH\n";
if ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_RHEL)
{
$strImage .= "RUN yum -y install openssh-server openssh-clients\n";
}
elsif ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_DEBIAN)
{
$strImage .=
"RUN apt-get update\n" .
"RUN apt-get -y install openssh-server\n";
}
$strImage .=
"RUN rm -f /etc/ssh/ssh_host_rsa_key*\n" .
"RUN ssh-keygen -t rsa -b 1024 -f /etc/ssh/ssh_host_rsa_key";
# Create PostgreSQL Group
$strImage .= "\n\n" . postgresGroupCreate($strOS);
# Add PostgreSQL packages
$strImage .= "\n\n# Add PostgreSQL packages\n";
if ($strOS eq VM_CO6)
{
$strImage .=
"RUN rpm -ivh http://yum.postgresql.org/9.0/redhat/rhel-6-x86_64/pgdg-centos90-9.0-5.noarch.rpm\n" .
"RUN rpm -ivh http://yum.postgresql.org/9.1/redhat/rhel-6-x86_64/pgdg-centos91-9.1-4.noarch.rpm\n" .
"RUN rpm -ivh http://yum.postgresql.org/9.2/redhat/rhel-6-x86_64/pgdg-centos92-9.2-6.noarch.rpm\n" .
"RUN rpm -ivh http://yum.postgresql.org/9.3/redhat/rhel-6-x86_64/pgdg-centos93-9.3-1.noarch.rpm\n" .
"RUN rpm -ivh http://yum.postgresql.org/9.4/redhat/rhel-6-x86_64/pgdg-centos94-9.4-1.noarch.rpm\n" .
"RUN rpm -ivh http://yum.postgresql.org/9.5/redhat/rhel-6-x86_64/pgdg-centos95-9.5-2.noarch.rpm\n" .
"RUN rpm -ivh http://yum.postgresql.org/9.6/redhat/rhel-6-x86_64/pgdg-centos96-9.6-1.noarch.rpm";
}
elsif ($strOS eq VM_CO7)
{
$strImage .=
"RUN rpm -ivh http://yum.postgresql.org/9.3/redhat/rhel-7-x86_64/pgdg-centos93-9.3-1.noarch.rpm\n" .
"RUN rpm -ivh http://yum.postgresql.org/9.4/redhat/rhel-7-x86_64/pgdg-centos94-9.4-1.noarch.rpm\n" .
"RUN rpm -ivh http://yum.postgresql.org/9.5/redhat/rhel-7-x86_64/pgdg-centos95-9.5-1.noarch.rpm\n" .
"RUN rpm -ivh http://yum.postgresql.org/9.6/redhat/rhel-7-x86_64/pgdg-centos96-9.6-1.noarch.rpm";
}
elsif ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_DEBIAN)
{
if ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_DEBIAN)
{
$strImage .=
"RUN apt-get install -y sudo wget\n";
}
$strImage .=
"RUN echo 'deb http://apt.postgresql.org/pub/repos/apt/ " .
$$oVm{$strOS}{&VM_OS_REPO} . "-pgdg main 9.6' >> /etc/apt/sources.list.d/pgdg.list\n" .
"RUN wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | apt-key add -\n" .
"RUN apt-get update";
}
# Create test group
$strImage .=
"\n\n# Create test group\n" .
groupCreate($strOS, TEST_GROUP, TEST_GROUP_ID) . "\n";
if ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_RHEL)
{
$strImage .=
"RUN yum -y install sudo\n" .
"RUN echo '%" . TEST_GROUP . " ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/" . TEST_GROUP . "\n" .
"RUN sed -i 's/^Defaults requiretty\$/\\# Defaults requiretty/' /etc/sudoers";
}
elsif ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_DEBIAN)
{
$strImage .=
"RUN sed -i 's/^\\\%admin.*\$/\\\%" . TEST_GROUP . " ALL\\=\\(ALL\\) NOPASSWD\\: ALL/' /etc/sudoers";
}
# Create test user
$strImage .=
"\n\n# Create test user\n" .
userCreate($strOS, TEST_USER, TEST_USER_ID, TEST_GROUP);
# Suppress dpkg interactive output
if ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_DEBIAN)
{
$strImage .=
"\n\n# Suppress dpkg interactive output\n" .
"RUN rm /etc/apt/apt.conf.d/70debconf";
}
# Start SSH when container starts
$strImage .=
"\n\n# Start SSH when container starts\n";
# This is required in newer versions of u12 containers - seems like a bug in the container
if ($strOS eq VM_U12)
{
$strImage .=
"RUN mkdir /var/run/sshd\n";
}
if ($strOS eq VM_U14 || $strOS eq VM_D8 || $strOS eq VM_U16)
{
$strImage .=
"ENTRYPOINT service ssh restart && bash";
}
else
{
$strImage .=
"ENTRYPOINT /usr/sbin/sshd -D";
}
# Write the image
containerWrite($strTempPath, $strImageName, $strImage, $bVmForce);
# Db image
###########################################################################################################################
foreach my $strDbVersion (@{$$oOS{db}})
{
my $strDbVersionNoDot = $strDbVersion;
$strDbVersionNoDot =~ s/\.//;
$strImageName = "${strOS}-db-${strDbVersionNoDot}";
&log(INFO, "Building ${strImageName} image...");
$strImage = "# Database Container\nFROM backrest/${strOS}-base";
# Create PostgreSQL User
$strImage .= "\n\n" . postgresUserCreate($strOS);
# Install SSH key
$strImage .=
"\n\n" . sshSetup($strOS, POSTGRES_USER, POSTGRES_GROUP);
# Install PostgreSQL
$strImage .=
"\n\n# Install PostgreSQL";
if ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_DEBIAN)
{
$strImage .=
"\nRUN apt-get install -y postgresql-${strDbVersion}" .
"\nRUN pg_dropcluster --stop ${strDbVersion} main";
}
elsif ($$oVm{$strOS}{&VM_OS_BASE} eq VM_OS_BASE_RHEL)
{
$strImage .=
"\nRUN yum -y install postgresql${strDbVersionNoDot}-server";
}
# Write the image
containerWrite($strTempPath, $strImageName, $strImage, $bVmForce);
}
# Db Doc image
###########################################################################################################################
$strImageName = "${strOS}-db-doc";
&log(INFO, "Building ${strImageName} image...");
$strImage = "# Database Doc Container\nFROM backrest/${strOS}-db-94";
# Create configuration file
$strImage .=
"\n\n" . backrestConfigCreate($strOS, POSTGRES_USER, POSTGRES_GROUP);
# Write the image
containerWrite($strTempPath, $strImageName, $strImage, $bVmForce);
# Backup image
###########################################################################################################################
$strImageName = "${strOS}-backup";
&log(INFO, "Building ${strImageName} image...");
$strImage = "# Backup Container\nFROM backrest/${strOS}-base";
# Create BackRest User
$strImage .= "\n\n" . backrestUserCreate($strOS);
# Install SSH key
$strImage .=
"\n\n" . sshSetup($strOS, BACKREST_USER, BACKREST_GROUP);
# Write the image
containerWrite($strTempPath, $strImageName, $strImage, $bVmForce);
# Backup Doc image
###########################################################################################################################
$strImageName = "${strOS}-backup-doc";
&log(INFO, "Building ${strImageName} image...");
$strImage = "# Backup Doc Container\nFROM backrest/${strOS}-backup";
# Create configuration file
$strImage .=
"\n\n" . backrestConfigCreate($strOS, BACKREST_USER, BACKREST_GROUP);
# Setup repository
$strImage .=
"\n\n" . repoSetup($strOS, BACKREST_USER, BACKREST_GROUP);
# Install Perl packages
$strImage .=
"\n\n" . perlInstall($strOS) . "\n";
# Write the image
containerWrite($strTempPath, $strImageName, $strImage, $bVmForce);
# Test image
###########################################################################################################################
foreach my $strDbVersion (@{$$oOS{db}})
{
my $strDbVersionNoDot = $strDbVersion;
$strDbVersionNoDot =~ s/\.//;
$strImageName = "${strOS}-test-${strDbVersionNoDot}";
&log(INFO, "Building ${strImageName} image...");
$strImage = "# Test Container\nFROM backrest/${strOS}-db-${strDbVersionNoDot}";
# Create BackRest User
$strImage .= "\n\n" . backrestUserCreate($strOS);
# Install SSH key
$strImage .=
"\n\n" . sshSetup($strOS, BACKREST_USER, BACKREST_GROUP);
# Install SSH key for vagrant user
$strImage .=
"\n\n" . sshSetup($strOS, TEST_USER, TEST_GROUP);
# Put vagrant user in postgres group so tests work properly (this will be removed in the future)
$strImage .=
"\n\n# Add postgres group to vagrant user\n" .
"RUN usermod -g " . BACKREST_GROUP . " -G " . TEST_GROUP . " " . TEST_USER;
# Install Perl packages
$strImage .=
"\n\n" . perlInstall($strOS);
# Make PostgreSQL home group readable
$strImage .=
"\n\n# Make vagrant home dir readable\n" .
"RUN chown -R vagrant:postgres /home/vagrant\n" .
"RUN chmod g+r,g+x /home/vagrant";
# Write the image
containerWrite($strTempPath, $strImageName, $strImage, $bVmForce);
}
}
}
push @EXPORT, qw(containerBuild);
1;