From e7669ea9970ca85b98bde36dce4c27fcde212996 Mon Sep 17 00:00:00 2001 From: qount25 Date: Tue, 1 Apr 2025 04:15:19 +0000 Subject: [PATCH 1/8] Use full pg version instead of major when forming package name --- lib/pgpm/deb/builder.rb | 4 ++-- lib/pgpm/deb/spec.rb | 8 ++++---- lib/pgpm/package/dependencies.rb | 6 +++--- lib/pgpm/rpm/spec.rb | 7 ++----- 4 files changed, 11 insertions(+), 14 deletions(-) diff --git a/lib/pgpm/deb/builder.rb b/lib/pgpm/deb/builder.rb index a036c8c..677d168 100644 --- a/lib/pgpm/deb/builder.rb +++ b/lib/pgpm/deb/builder.rb @@ -34,7 +34,7 @@ def build # Depends on postgres version and arch def image_name - "quay.io/qount25/pgpm-debian-pg#{@spec.package.postgres_major_version}-#{@spec.arch}" + "quay.io/qount25/pgpm-debian-pg#{@spec.package.postgres_version}-#{@spec.arch}" end def prepare_versioned_source @@ -88,7 +88,7 @@ def prepare_default_source # 2. Determine the name of the .control file inside the versioned build deb_dir = "#{pbuilds_dir}/#{build_dir}/build/#{@spec.deb_pkg_name(:versioned)}-0/debian/#{@spec.deb_pkg_name(:versioned)}" - control_fn = "#{deb_dir}/usr/share/postgresql/#{@spec.package.postgres_major_version}/extension/#{@spec.package.extension_name}--#{@spec.package.version}.control" + control_fn = "#{deb_dir}/usr/share/postgresql/#{@spec.package.postgres_version}/extension/#{@spec.package.extension_name}--#{@spec.package.version}.control" # 3. Copy .control file to the source-default dir puts "Copying #{control_fn} into /root/pgpm/source-default/" diff --git a/lib/pgpm/deb/spec.rb b/lib/pgpm/deb/spec.rb index c3356f6..de36d9e 100644 --- a/lib/pgpm/deb/spec.rb +++ b/lib/pgpm/deb/spec.rb @@ -7,12 +7,12 @@ module Pgpm module Deb class Spec - attr_reader :package, :release, :postgres_version, :postgres_distribution + attr_reader :package, :release, :postgres_distribution def initialize(package) @postgres_distribution = Pgpm::Postgres::Distribution.in_scope @package = package - @package.postgres_major_version = @postgres_distribution.major_version + @package.postgres_version = @postgres_distribution.version @release = 1 end @@ -38,9 +38,9 @@ def source_version def deb_pkg_name(type = :versioned) if type == :versioned - "#{@package.name.gsub("_", "-")}+#{source_version}-pg#{@package.postgres_major_version}" + "#{@package.name.gsub("_", "-")}+#{source_version}-pg#{@package.postgres_version}" else - "#{@package.name.gsub("_", "-")}-pg#{@package.postgres_major_version}" + "#{@package.name.gsub("_", "-")}-pg#{@package.postgres_version}" end end diff --git a/lib/pgpm/package/dependencies.rb b/lib/pgpm/package/dependencies.rb index 8869156..80b07fc 100644 --- a/lib/pgpm/package/dependencies.rb +++ b/lib/pgpm/package/dependencies.rb @@ -5,14 +5,14 @@ module Pgpm class Package module Dependencies - attr_accessor :postgres_major_version + attr_accessor :postgres_version def build_dependencies case Pgpm::OS.in_scope.class.name when "debian", "ubuntu" deps = [ - "postgresql-#{postgres_major_version}", - "postgresql-server-dev-#{postgres_major_version}", + "postgresql-#{postgres_version}", + "postgresql-server-dev-#{postgres_version}", "postgresql-common" ] if native? diff --git a/lib/pgpm/rpm/spec.rb b/lib/pgpm/rpm/spec.rb index fbc8aef..840cbee 100644 --- a/lib/pgpm/rpm/spec.rb +++ b/lib/pgpm/rpm/spec.rb @@ -6,16 +6,13 @@ module Pgpm module RPM class Spec - attr_reader :package, :release, :postgres_version, :postgres_distribution + attr_reader :package, :release, :postgres_distribution def initialize(package) @postgres_distribution = Pgpm::Postgres::Distribution.in_scope @package = package + @package.postgres_version = @postgres_distribution.version @release = 1 - - # Needed in order to return correct dependencies for the selected - # version of postgres and selected OS. - @package.postgres_major_version = @postgres_distribution.major_version end def versionless From 9fd9648a8003a3e1e22d08a30e295fb9b8cd3b04 Mon Sep 17 00:00:00 2001 From: qount25 Date: Tue, 1 Apr 2025 07:29:34 +0000 Subject: [PATCH 2/8] Use base deb podman image and patch it locally with correct pg version installed inside chroot --- lib/pgpm/deb/Dockerfile | 3 -- lib/pgpm/deb/builder.rb | 49 ++++++++++++++++--- lib/pgpm/deb/pbuilder_install_script.sh | 21 -------- lib/pgpm/deb/spec.rb | 4 +- .../templates/pbuilder_install_script.sh.erb | 38 ++++++++++++++ lib/pgpm/package/dependencies.rb | 14 ++++-- lib/pgpm/rpm/spec.rb | 3 +- 7 files changed, 92 insertions(+), 40 deletions(-) delete mode 100644 lib/pgpm/deb/pbuilder_install_script.sh create mode 100644 lib/pgpm/deb/templates/pbuilder_install_script.sh.erb diff --git a/lib/pgpm/deb/Dockerfile b/lib/pgpm/deb/Dockerfile index 46a9940..d2b8bd2 100644 --- a/lib/pgpm/deb/Dockerfile +++ b/lib/pgpm/deb/Dockerfile @@ -26,6 +26,3 @@ RUN echo 'MIRRORSITE=http://deb.debian.org/debian' > /etc/pbuilderrc RUN echo 'AUTO_DEBSIGN=${AUTO_DEBSIGN:-no}' > /root/.pbuilderrc RUN echo 'HOOKDIR=/var/cache/pbuilder/hooks' >> /root/.pbuilderrc RUN --security=insecure pbuilder create - -COPY pbuilder_install_script.sh /root/pbuilder_install_script.sh -RUN --security=insecure pbuilder execute --save-after-exec /root/pbuilder_install_script.sh diff --git a/lib/pgpm/deb/builder.rb b/lib/pgpm/deb/builder.rb index 677d168..dd31b50 100644 --- a/lib/pgpm/deb/builder.rb +++ b/lib/pgpm/deb/builder.rb @@ -1,7 +1,6 @@ # frozen_string_literal: true require "English" -require "debug" module Pgpm module Deb @@ -13,7 +12,7 @@ def initialize(spec) end def build - pull_image + prepare_image start_container patch_pbuilder @@ -32,9 +31,16 @@ def build private - # Depends on postgres version and arch + # Only depends on the arch -- this is the image being pulled from + # a remote repo, which is then used to build a local image with correct + # postgres version installed inside its pbuilder's chroot. + def base_image_name + "quay.io/qount25/pgpm-debian-#{@spec.arch}" + end + + # Locally built image with correct chroot installed. def image_name - "quay.io/qount25/pgpm-debian-pg#{@spec.package.postgres_version}-#{@spec.arch}" + "pgpm-debian-pg#{@spec.package.postgres_version}-#{@spec.arch}" end def prepare_versioned_source @@ -102,18 +108,45 @@ def prepare_default_source end end - def pull_image + def prepare_image puts "Checking if podman image exists..." # Check if image exists system("podman image exists #{image_name}") - if $CHILD_STATUS.to_i.positive? # image doesn't exist -- pull image from a remote repository - puts " No. Pulling image #{image_name}..." - system("podman pull #{image_name}") + if $CHILD_STATUS.to_i.positive? + puts " Image for the specific pg version doesn't exist. Will build." + system("podman image exists #{base_image_name}") + if $CHILD_STATUS.to_i.positive? + puts " Base image doesn't exist. Pulling it..." + system("podman pull #{base_image_name}") + end + build_local_image else puts " Yes, image #{image_name} already exists! OK" end end + def build_local_image + puts " Building local #{image_name}..." + system("podman create -it --privileged --tmpfs /tmp --name pgpm-deb-tmp #{base_image_name}") + system("podman start pgpm-deb-tmp") + + # Generate pbuilder_install script.sh, copy it inside the image + pbuild_install_script_path = "#{@pgpm_dir}/pbuilder_install_script.sh" + puts " Generating #{pbuild_install_script_path}..." + File.write "#{pbuild_install_script_path}", @spec.generate("pbuilder_install_script.sh") + system("podman container cp #{pbuild_install_script_path} pgpm-deb-tmp:/root/") + + # This command installs relevant postgresql packages into the chroot + # base image inside the container (along with some other necessary + # packages) and saves chroot base image with these changes. + puts " Updating chroot image..." + system("podman exec -w /root pgpm-deb-tmp /bin/bash -c 'fakeroot pbuilder execute --save-after-exec ./pbuilder_install_script.sh'") + + system("podman stop pgpm-deb-tmp") + system("podman commit pgpm-deb-tmp #{image_name}") + system("podman container rm pgpm-deb-tmp") + end + def generate_deb_src_files(pkg_type = :versioned) puts "Generating debian files..." Dir.mkdir "#{@pgpm_dir}/source-#{pkg_type}/debian" diff --git a/lib/pgpm/deb/pbuilder_install_script.sh b/lib/pgpm/deb/pbuilder_install_script.sh deleted file mode 100644 index 484850f..0000000 --- a/lib/pgpm/deb/pbuilder_install_script.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env bash -apt update -DEBIAN_FRONTEND=noninteractive apt -y install build-essential curl lsb-release ca-certificates - -### PostgreSQL installation -# -install -d /usr/share/postgresql-common/pgdg -curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc - -# Create the repository configuration file: -sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' - -# Update the package lists: -apt update - -# Install the latest version of PostgreSQL: -# If you want a specific version, use 'postgresql-16' or similar instead of 'postgresql' -apt -y install postgresql-17 postgresql-server-dev-17 postgresql-common -# -### END OF PostgreSQL installation - diff --git a/lib/pgpm/deb/spec.rb b/lib/pgpm/deb/spec.rb index de36d9e..f5702c7 100644 --- a/lib/pgpm/deb/spec.rb +++ b/lib/pgpm/deb/spec.rb @@ -7,12 +7,10 @@ module Pgpm module Deb class Spec - attr_reader :package, :release, :postgres_distribution + attr_reader :package, :release def initialize(package) - @postgres_distribution = Pgpm::Postgres::Distribution.in_scope @package = package - @package.postgres_version = @postgres_distribution.version @release = 1 end diff --git a/lib/pgpm/deb/templates/pbuilder_install_script.sh.erb b/lib/pgpm/deb/templates/pbuilder_install_script.sh.erb new file mode 100644 index 0000000..af64b73 --- /dev/null +++ b/lib/pgpm/deb/templates/pbuilder_install_script.sh.erb @@ -0,0 +1,38 @@ +#!/usr/bin/env bash + +# Run this script with: +# fakeroot pbuilder execute --save-after-exec ./pbuilder_install_script.sh + +apt update +DEBIAN_FRONTEND=noninteractive apt -y install \ + build-essential curl lsb-release ca-certificates automake autopoint \ + autotools-dev bsdextrautils debhelper dh-autoreconf dh-strip-nondeterminism \ + dwz file gettext gettext-base groff-base intltool-debian libarchive-zip-perl \ + libdebhelper-perl libelf1t64 libfile-stripnondeterminism-perl libmagic-mgc \ + libmagic1t64 libpipeline1 libtool libuchardet0 man-db po-debconf + +### PostgreSQL installation +# +install -d /usr/share/postgresql-common/pgdg +curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https://www.postgresql.org/media/keys/ACCC4CF8.asc + +# Create the repository configuration file: +sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' + +# Update the package lists: +apt update + +# Install PostgreSQL. We first try a package with the full version name, but if +# (such as postgresql-17.4), but if that's not the name that exists in the apt +# repository, we use postgresql-17 instead. +PG_VERSION=<%= @package.postgres_version(:major) %> + +# Checking if the output is empty, because `apt search` returns status 0 +# even if doesn't find anything. +if [[ $(apt-cache search --names-only postgresql-<%= @package.postgres_version %> | head -c1 | wc -c) -ne 0 ]]; then + PG_VERSION=<%= @package.postgres_version %> +fi + +apt -y install postgresql-$PG_VERSION \ + postgresql-server-dev-$PG_VERSION \ + postgresql-common diff --git a/lib/pgpm/package/dependencies.rb b/lib/pgpm/package/dependencies.rb index 80b07fc..d2a0963 100644 --- a/lib/pgpm/package/dependencies.rb +++ b/lib/pgpm/package/dependencies.rb @@ -11,8 +11,8 @@ def build_dependencies case Pgpm::OS.in_scope.class.name when "debian", "ubuntu" deps = [ - "postgresql-#{postgres_version}", - "postgresql-server-dev-#{postgres_version}", + "postgresql-#{postgres_version(:major)}", + "postgresql-server-dev-#{postgres_version(:major)}", "postgresql-common" ] if native? @@ -26,7 +26,7 @@ def build_dependencies def dependencies case Pgpm::OS.in_scope.class.name when "debian", "ubuntu" - ["postgresql-#{postgres_major_version}"] + ["postgresql-#{postgres_version(:major)}"] when "rocky+epel-9", "redhat", "fedora" [] end @@ -44,6 +44,14 @@ def topologically_ordered_with_dependencies TopologicalPackageSorter.new([self, *all_requirements]).sorted_packages end + def postgres_version(version_type=:major_minor) + v = Pgpm::Postgres::Distribution.in_scope.version + if version_type == :major + v = v.split(".").first + end + v + end + class TopologicalPackageSorter include TSort diff --git a/lib/pgpm/rpm/spec.rb b/lib/pgpm/rpm/spec.rb index 840cbee..05e26f7 100644 --- a/lib/pgpm/rpm/spec.rb +++ b/lib/pgpm/rpm/spec.rb @@ -6,12 +6,11 @@ module Pgpm module RPM class Spec - attr_reader :package, :release, :postgres_distribution + attr_reader :package, :release def initialize(package) @postgres_distribution = Pgpm::Postgres::Distribution.in_scope @package = package - @package.postgres_version = @postgres_distribution.version @release = 1 end From 2ae1b01cbb9653153185cc57e6dbf34a4f7414bb Mon Sep 17 00:00:00 2001 From: qount25 Date: Wed, 2 Apr 2025 08:13:02 +0000 Subject: [PATCH 3/8] Problem: users cannot set which minor version of postgresql package to use when building dev pkg In its official deb repository, postgresql packages may have the following names: postgresql-17 postgresql-16 postgresql-15 etc. The problem here is that the latest minor version will be installed, wherease users may want a different version. Solution: packages have versions. Inside pbuilder_install_script.sh.erb we pick up which version our user wants and match it agains what's available. If it exists, we install that particular version: ... apt -y install postgresql-$PG_MAJOR_VERSION=$pkg_version ... And then build the local podman image named after the chosen postgresql version. If user selected postgresql version 17.14 on amd64, the image will be called: pgpm-debian-pg17.4-amd64 BONUS FIX: LD_CONFIG error messages are no longer present! --- lib/pgpm/deb/builder.rb | 15 +++++- lib/pgpm/deb/spec.rb | 1 + .../templates/pbuilder_install_script.sh.erb | 51 ++++++++++++++----- lib/pgpm/package/dependencies.rb | 6 +-- 4 files changed, 54 insertions(+), 19 deletions(-) diff --git a/lib/pgpm/deb/builder.rb b/lib/pgpm/deb/builder.rb index dd31b50..e9e383b 100644 --- a/lib/pgpm/deb/builder.rb +++ b/lib/pgpm/deb/builder.rb @@ -142,9 +142,20 @@ def build_local_image puts " Updating chroot image..." system("podman exec -w /root pgpm-deb-tmp /bin/bash -c 'fakeroot pbuilder execute --save-after-exec ./pbuilder_install_script.sh'") - system("podman stop pgpm-deb-tmp") + # Exiting -- most likely error occurred because we cannot find the same + # postgresql version in the Debian repository. The bash script + # will do error reporting for us, so we just exit. + if $CHILD_STATUS.to_i.positive? + stop_and_remove_deb_tmp_image + exit 1 + end system("podman commit pgpm-deb-tmp #{image_name}") - system("podman container rm pgpm-deb-tmp") + stop_and_remove_deb_tmp_image + end + + def stop_and_remove_deb_tmp_image + system("podman stop pgpm-deb-tmp") + system("podman container rm pgpm-deb-tmp") end def generate_deb_src_files(pkg_type = :versioned) diff --git a/lib/pgpm/deb/spec.rb b/lib/pgpm/deb/spec.rb index f5702c7..eca4805 100644 --- a/lib/pgpm/deb/spec.rb +++ b/lib/pgpm/deb/spec.rb @@ -60,6 +60,7 @@ def cmds_if_not_empty(cmds, else_echo) cmds.map! { |c| c.gsub("$", "$$") } cmds.join("\t") end + end end end diff --git a/lib/pgpm/deb/templates/pbuilder_install_script.sh.erb b/lib/pgpm/deb/templates/pbuilder_install_script.sh.erb index af64b73..0fe612d 100644 --- a/lib/pgpm/deb/templates/pbuilder_install_script.sh.erb +++ b/lib/pgpm/deb/templates/pbuilder_install_script.sh.erb @@ -1,8 +1,19 @@ #!/usr/bin/env bash # Run this script with: -# fakeroot pbuilder execute --save-after-exec ./pbuilder_install_script.sh +# fakeroot pbuilder execute --save-after-exec path/to/pbuilder_install_script.sh + +# This helps us avoid almost all instances of a very annoying: +# +# ERROR: ld.so: object 'libfakeroot-sysv.so' from LD_PRELOAD cannot be preloaded... +# +# which isn't critical, but is polluting the output and makes debugging or +# simply reading the output more difficult. +export LD_PRELOAD="$(find / -name libfakeroot-sysv.so 2>/dev/null)" + +# These packages are universally required by pbuilder, so we pre-install them +# inside our chroot. apt update DEBIAN_FRONTEND=noninteractive apt -y install \ build-essential curl lsb-release ca-certificates automake autopoint \ @@ -19,20 +30,32 @@ curl -o /usr/share/postgresql-common/pgdg/apt.postgresql.org.asc --fail https:// # Create the repository configuration file: sh -c 'echo "deb [signed-by=/usr/share/postgresql-common/pgdg/apt.postgresql.org.asc] https://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' +# Add archive repos containing all postgres versions deleted from +# apt.postgresql.org. For example, when version 17.4 came out, version 17.3 +# was moved to the archive-apt source. We want all of them, because we don't know +# ahead of time which version is going to be required by the user. +apt_sources_fn="/etc/apt/sources.list.d/pgdg.list" +cat $apt_sources_fn | grep 's|https://apt|https://apt-archive' >> $apt_sources_fn + # Update the package lists: apt update -# Install PostgreSQL. We first try a package with the full version name, but if -# (such as postgresql-17.4), but if that's not the name that exists in the apt -# repository, we use postgresql-17 instead. -PG_VERSION=<%= @package.postgres_version(:major) %> - -# Checking if the output is empty, because `apt search` returns status 0 -# even if doesn't find anything. -if [[ $(apt-cache search --names-only postgresql-<%= @package.postgres_version %> | head -c1 | wc -c) -ne 0 ]]; then - PG_VERSION=<%= @package.postgres_version %> +PG_VERSION=<%= @package.postgres_version %> +PG_MAJOR_VERSION=<%= @package.postgres_version(:major) %> + +# Let's check if the version we're trying to install actually exists. +pkg="$(apt-cache madison postgresql-$PG_MAJOR_VERSION | grep " | $PG_VERSION" | head -n1)" +if [[ "$pkg" == "" ]]; then + # If it doesn't we exit with status 1 and an explanation of an error. This will + # trigger the caller (spec.rb) to also exit with status one and, thus, will + # not build a local image -- because user-requested version of postgresql + # cannot be found in the repository. + >&2 echo "ERROR:" + >&2 echo " Couldn't find postgresql-$PG_MAJOR_VERSION package with version $PG_VERSION." + exit 1 +else + pkg_version="$(echo "$pkg" | cut -d "|" -f 2 | xargs)" + apt -y install postgresql-$PG_MAJOR_VERSION=$pkg_version \ + postgresql-server-dev-$PG_MAJOR_VERSION=$pkg_version \ + postgresql-common fi - -apt -y install postgresql-$PG_VERSION \ - postgresql-server-dev-$PG_VERSION \ - postgresql-common diff --git a/lib/pgpm/package/dependencies.rb b/lib/pgpm/package/dependencies.rb index d2a0963..54412cb 100644 --- a/lib/pgpm/package/dependencies.rb +++ b/lib/pgpm/package/dependencies.rb @@ -11,8 +11,8 @@ def build_dependencies case Pgpm::OS.in_scope.class.name when "debian", "ubuntu" deps = [ - "postgresql-#{postgres_version(:major)}", - "postgresql-server-dev-#{postgres_version(:major)}", + "postgresql-#{postgres_version(:major)} (>= #{postgres_version})", + "postgresql-server-dev-#{postgres_version(:major)} (>= #{postgres_version})", "postgresql-common" ] if native? @@ -26,7 +26,7 @@ def build_dependencies def dependencies case Pgpm::OS.in_scope.class.name when "debian", "ubuntu" - ["postgresql-#{postgres_version(:major)}"] + ["postgresql-#{postgres_version(:major)} (>= #{postgres_version})"] when "rocky+epel-9", "redhat", "fedora" [] end From 0118b31168dc63c9ca27d1edd15160166207acf2 Mon Sep 17 00:00:00 2001 From: qount25 Date: Thu, 3 Apr 2025 09:24:16 +0000 Subject: [PATCH 4/8] Problem: podman error on SOME freshly installed systems when running the first build Solution: adding a documentation md file on how to solve it by followin a few simple steps --- .gitignore | 3 +-- doc/podman.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 2 deletions(-) create mode 100644 doc/podman.md diff --git a/.gitignore b/.gitignore index 3fe11ee..56b474c 100644 --- a/.gitignore +++ b/.gitignore @@ -2,9 +2,8 @@ /.yardoc /_yardoc/ /coverage/ -/doc/ /pkg/ /spec/reports/ /tmp/ .idea -Gemfile.lock \ No newline at end of file +Gemfile.lock diff --git a/doc/podman.md b/doc/podman.md new file mode 100644 index 0000000..dd36c44 --- /dev/null +++ b/doc/podman.md @@ -0,0 +1,44 @@ +Known podman issues +=================== + +"Unable to start container" error +--------------------------------- +When you first build a package, podman downloads the base image and attempts +to create a local image with correct version PostgreSQL installed into it. +However on some systems, running podman may initially result in the following +error: + +``` +Error: unable to start container "[CONTAINER_ID]": container create failed (no logs from conmon): conmon bytes "": readObjectStart: expect { or n, but found , error found in #0 byte of ...||..., bigger context ...||... +``` + +To fix this issue the following steps need to be performed: + +1. Wipe all podman runtime and configuration: + + pkill -9 -f 'conmon|podman' + rm -rf ~/.local/share/containers/ + rm -rf ~/.config/containers/ + rm -rf /run/user/$(id -u)/libpod/ + podman system reset --force + +2. Reinstall podman and its components: + + sudo apt reinstall podman conmon runc crun + +3. Create storage settings conf file: + + mkdir -p ~/.config/containers/ + touch ~/.config/containers/storage.conf + + # Add the following lines to the newly + # created ~/.config/containers/storage.conf: + # + [storage] + driver = "overlay" + graphroot = "/home/$USER/.local/share/containers/storage" + runroot = "/run/user/$(id -u)/containers" + +4. Restart the service (if applicable): + + service podman restart From 8977f44ddb1b2d954199b9da94da3d59e71afef0 Mon Sep 17 00:00:00 2001 From: qount25 Date: Sat, 5 Apr 2025 03:32:54 +0000 Subject: [PATCH 5/8] Problem: pbuilder uses tar, which results in "Cannot readlink: Invalid argument" The issue is present on podman hosts when they are themslves KVM guests, but is not present if podman is used on host OS, which iteself is installed on bare metal. Solution: create `faketar` script and patch pbuilder to use it instead of tar. The `faketar` script uses simple `cp` and `mv` commands, which not only help us avoid the issue with `tar`, but also make our builds faster by skipping compression & decompression of tgz. Due to a rather esoteric nature of the problem `faketar` script is reasonable workaround, which also saves on build time. --- lib/pgpm/deb/Dockerfile | 10 +++++++--- lib/pgpm/deb/builder.rb | 10 +++++++--- lib/pgpm/deb/scripts/faketar | 26 ++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 6 deletions(-) create mode 100755 lib/pgpm/deb/scripts/faketar diff --git a/lib/pgpm/deb/Dockerfile b/lib/pgpm/deb/Dockerfile index d2b8bd2..8f2601b 100644 --- a/lib/pgpm/deb/Dockerfile +++ b/lib/pgpm/deb/Dockerfile @@ -7,7 +7,7 @@ # { "builder": {"Entitlements": {"security-insecure": true }} } # ``` # ``` -# DOCKER_BUILDKIT=1 docker build --allow security.insecure -t IMAGE_NAME /path/to/pgpm +# DOCKER_BUILDKIT=1 docker build --allow security.insecure -t IMAGE_NAME . # ``` # This Dockerfile is used to build a Debian image, which includes pbuilder and @@ -21,8 +21,12 @@ MAINTAINER PGPM Debian Maintainer debian.maintainer@postgres.pm VOLUME /proc ARG DEBIAN_FRONTEND=noninteractive RUN apt update -RUN apt install -y build-essential pbuilder fakeroot fakechroot +RUN apt install -y build-essential pbuilder fakeroot fakechroot vim ripgrep RUN echo 'MIRRORSITE=http://deb.debian.org/debian' > /etc/pbuilderrc RUN echo 'AUTO_DEBSIGN=${AUTO_DEBSIGN:-no}' > /root/.pbuilderrc RUN echo 'HOOKDIR=/var/cache/pbuilder/hooks' >> /root/.pbuilderrc -RUN --security=insecure pbuilder create +COPY scripts/faketar /usr/bin/ +RUN chmod +x /usr/bin/faketar +RUN sed -E -i "s/local TAR=tar/local TAR=faketar/" /usr/lib/pbuilder/pbuilder-modules +RUN sed -E -i "s/if [!] tar -c --use-compress-program/if ! faketar -c --use-compress-program/" /usr/lib/pbuilder/pbuilder-modules +RUN --security=insecure fakeroot pbuilder create diff --git a/lib/pgpm/deb/builder.rb b/lib/pgpm/deb/builder.rb index e9e383b..eac40e5 100644 --- a/lib/pgpm/deb/builder.rb +++ b/lib/pgpm/deb/builder.rb @@ -14,7 +14,6 @@ def initialize(spec) def build prepare_image start_container - patch_pbuilder prepare_versioned_source generate_deb_src_files(:versioned) @@ -127,9 +126,12 @@ def prepare_image def build_local_image puts " Building local #{image_name}..." - system("podman create -it --privileged --tmpfs /tmp --name pgpm-deb-tmp #{base_image_name}") + container_opts = "-it --privileged --tmpfs /tmp --name pgpm-deb-tmp" + system("podman create #{container_opts} #{base_image_name}") system("podman start pgpm-deb-tmp") + patch_pbuilder + # Generate pbuilder_install script.sh, copy it inside the image pbuild_install_script_path = "#{@pgpm_dir}/pbuilder_install_script.sh" puts " Generating #{pbuild_install_script_path}..." @@ -194,7 +196,9 @@ def start_container # a result. def patch_pbuilder cmd = "sed -E -i \"s/(^function clean_subdirectories.*$)/\\1\\n return/g\" /usr/lib/pbuilder/pbuilder-modules" - system("podman exec #{@container_name} /bin/bash -c '#{cmd}'") + system("podman exec pgpm-deb-tmp /bin/bash -c '#{cmd}'") + cmd = "sed -E -i \"s/if [[] [!] -f [\\\"]([$]BASETGZ)/if [ ! -d \\\"\\1/\" /usr/lib/pbuilder/pbuilder-modules" + system("podman exec pgpm-deb-tmp /bin/bash -c '#{cmd}'") end def run_build(pkg_type = :versioned) diff --git a/lib/pgpm/deb/scripts/faketar b/lib/pgpm/deb/scripts/faketar new file mode 100755 index 0000000..1e0e748 --- /dev/null +++ b/lib/pgpm/deb/scripts/faketar @@ -0,0 +1,26 @@ +#!/usr/bin/env bash + +ARGS="$@" +echo "faketar ${ARGS[@]}" + +if [[ " ${ARGS[*]} " =~ [[:space:]]-x[[:space:]] ]]; then # compress + # Replacing this command: + # tar -x -p -f "$BASETGZ" + src="$4" + echo "Copying $src/* to $(pwd)" + cp -pur $src/* ./ +elif [[ " ${ARGS[*]} " =~ [[:space:]]-c[[:space:]] ]]; then # extract + # Replacing this command: + # tar -c --use-compress-program "$COMPRESSPROG" -f "${BASETGZ}.tmp" ./* + target="$5" + src="." + mkdir $target + echo "Moving $src/* to $target/" + mv $src/* $target/ + # Remove existing directory into which we move the contents. + # Otherwise, pbuilder (when it calls `mv`) will move $target inside it, + # instead of copying $target/* into it. + if [[ -d "${target%".tmp"}" ]]; then + rm -rf "${target%".tmp"}" + fi +fi From e7f816c1f6b579d36852f23c03f54c74ef4870e0 Mon Sep 17 00:00:00 2001 From: qount25 Date: Sun, 6 Apr 2025 14:30:34 +0000 Subject: [PATCH 6/8] Fix: nil error in Timescaledb package, deps should've been an empty array --- packages/timescale/timescaledb.rb | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/timescale/timescaledb.rb b/packages/timescale/timescaledb.rb index 59f0d55..5a7747d 100644 --- a/packages/timescale/timescaledb.rb +++ b/packages/timescale/timescaledb.rb @@ -28,6 +28,8 @@ def dependencies deps = case Pgpm::OS.in_scope.class.name when "rocky+epel-9", "redhat", "fedora" ["openssl"] + else + [] end super + deps end From cfa3032f9f59fe3d5da358b7143bd01a44d9522f Mon Sep 17 00:00:00 2001 From: qount25 Date: Sun, 6 Apr 2025 14:39:34 +0000 Subject: [PATCH 7/8] Fix: rubocop errors --- lib/pgpm/deb/builder.rb | 54 ++++++++++++++++---------------- lib/pgpm/deb/spec.rb | 1 - lib/pgpm/package/dependencies.rb | 4 +-- 3 files changed, 28 insertions(+), 31 deletions(-) diff --git a/lib/pgpm/deb/builder.rb b/lib/pgpm/deb/builder.rb index eac40e5..5e0a927 100644 --- a/lib/pgpm/deb/builder.rb +++ b/lib/pgpm/deb/builder.rb @@ -125,34 +125,34 @@ def prepare_image end def build_local_image - puts " Building local #{image_name}..." - container_opts = "-it --privileged --tmpfs /tmp --name pgpm-deb-tmp" - system("podman create #{container_opts} #{base_image_name}") - system("podman start pgpm-deb-tmp") - - patch_pbuilder - - # Generate pbuilder_install script.sh, copy it inside the image - pbuild_install_script_path = "#{@pgpm_dir}/pbuilder_install_script.sh" - puts " Generating #{pbuild_install_script_path}..." - File.write "#{pbuild_install_script_path}", @spec.generate("pbuilder_install_script.sh") - system("podman container cp #{pbuild_install_script_path} pgpm-deb-tmp:/root/") - - # This command installs relevant postgresql packages into the chroot - # base image inside the container (along with some other necessary - # packages) and saves chroot base image with these changes. - puts " Updating chroot image..." - system("podman exec -w /root pgpm-deb-tmp /bin/bash -c 'fakeroot pbuilder execute --save-after-exec ./pbuilder_install_script.sh'") - - # Exiting -- most likely error occurred because we cannot find the same - # postgresql version in the Debian repository. The bash script - # will do error reporting for us, so we just exit. - if $CHILD_STATUS.to_i.positive? - stop_and_remove_deb_tmp_image - exit 1 - end - system("podman commit pgpm-deb-tmp #{image_name}") + puts " Building local #{image_name}..." + container_opts = "-it --privileged --tmpfs /tmp --name pgpm-deb-tmp" + system("podman create #{container_opts} #{base_image_name}") + system("podman start pgpm-deb-tmp") + + patch_pbuilder + + # Generate pbuilder_install script.sh, copy it inside the image + pbuild_install_script_path = "#{@pgpm_dir}/pbuilder_install_script.sh" + puts " Generating #{pbuild_install_script_path}..." + File.write pbuild_install_script_path.to_s, @spec.generate("pbuilder_install_script.sh") + system("podman container cp #{pbuild_install_script_path} pgpm-deb-tmp:/root/") + + # This command installs relevant postgresql packages into the chroot + # base image inside the container (along with some other necessary + # packages) and saves chroot base image with these changes. + puts " Updating chroot image..." + system("podman exec -w /root pgpm-deb-tmp /bin/bash -c 'fakeroot pbuilder execute --save-after-exec ./pbuilder_install_script.sh'") + + # Exiting -- most likely error occurred because we cannot find the same + # postgresql version in the Debian repository. The bash script + # will do error reporting for us, so we just exit. + if $CHILD_STATUS.to_i.positive? stop_and_remove_deb_tmp_image + exit 1 + end + system("podman commit pgpm-deb-tmp #{image_name}") + stop_and_remove_deb_tmp_image end def stop_and_remove_deb_tmp_image diff --git a/lib/pgpm/deb/spec.rb b/lib/pgpm/deb/spec.rb index eca4805..f5702c7 100644 --- a/lib/pgpm/deb/spec.rb +++ b/lib/pgpm/deb/spec.rb @@ -60,7 +60,6 @@ def cmds_if_not_empty(cmds, else_echo) cmds.map! { |c| c.gsub("$", "$$") } cmds.join("\t") end - end end end diff --git a/lib/pgpm/package/dependencies.rb b/lib/pgpm/package/dependencies.rb index 54412cb..fe66296 100644 --- a/lib/pgpm/package/dependencies.rb +++ b/lib/pgpm/package/dependencies.rb @@ -5,8 +5,6 @@ module Pgpm class Package module Dependencies - attr_accessor :postgres_version - def build_dependencies case Pgpm::OS.in_scope.class.name when "debian", "ubuntu" @@ -44,7 +42,7 @@ def topologically_ordered_with_dependencies TopologicalPackageSorter.new([self, *all_requirements]).sorted_packages end - def postgres_version(version_type=:major_minor) + def postgres_version(version_type = :major_minor) v = Pgpm::Postgres::Distribution.in_scope.version if version_type == :major v = v.split(".").first From a6b6c4ebdcbde5faa63933e6922497665e404c1d Mon Sep 17 00:00:00 2001 From: qount25 Date: Mon, 7 Apr 2025 14:07:19 +0000 Subject: [PATCH 8/8] Dockerfile comment: vim and ripgres are for debugging! --- lib/pgpm/deb/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/lib/pgpm/deb/Dockerfile b/lib/pgpm/deb/Dockerfile index 8f2601b..9f07dd2 100644 --- a/lib/pgpm/deb/Dockerfile +++ b/lib/pgpm/deb/Dockerfile @@ -21,7 +21,8 @@ MAINTAINER PGPM Debian Maintainer debian.maintainer@postgres.pm VOLUME /proc ARG DEBIAN_FRONTEND=noninteractive RUN apt update -RUN apt install -y build-essential pbuilder fakeroot fakechroot vim ripgrep +RUN apt install -y build-essential pbuilder fakeroot fakechroot +RUN apt install -y vim ripgrep # for ease of debugging RUN echo 'MIRRORSITE=http://deb.debian.org/debian' > /etc/pbuilderrc RUN echo 'AUTO_DEBSIGN=${AUTO_DEBSIGN:-no}' > /root/.pbuilderrc RUN echo 'HOOKDIR=/var/cache/pbuilder/hooks' >> /root/.pbuilderrc