vendor in latest buildah

Signed-off-by: Paul Holzinger <pholzing@redhat.com>
This commit is contained in:
Paul Holzinger
2023-06-27 15:15:57 +02:00
parent 6eaf8a271d
commit 0f4c86e267
22 changed files with 435 additions and 499 deletions

6
go.mod
View File

@ -12,14 +12,14 @@ require (
github.com/container-orchestrated-devices/container-device-interface v0.5.4 github.com/container-orchestrated-devices/container-device-interface v0.5.4
github.com/containernetworking/cni v1.1.2 github.com/containernetworking/cni v1.1.2
github.com/containernetworking/plugins v1.3.0 github.com/containernetworking/plugins v1.3.0
github.com/containers/buildah v1.30.1-0.20230504052500-e925b5852e07 github.com/containers/buildah v1.30.1-0.20230627110136-33b7088fec7b
github.com/containers/common v0.53.1-0.20230626115555-370c89881624 github.com/containers/common v0.53.1-0.20230627061926-e6f314e59b81
github.com/containers/conmon v2.0.20+incompatible github.com/containers/conmon v2.0.20+incompatible
github.com/containers/image/v5 v5.25.1-0.20230623174242-68798a22ce3e github.com/containers/image/v5 v5.25.1-0.20230623174242-68798a22ce3e
github.com/containers/libhvee v0.0.5 github.com/containers/libhvee v0.0.5
github.com/containers/ocicrypt v1.1.7 github.com/containers/ocicrypt v1.1.7
github.com/containers/psgo v1.8.0 github.com/containers/psgo v1.8.0
github.com/containers/storage v1.46.2-0.20230621123301-73f29956326d github.com/containers/storage v1.47.0
github.com/coreos/go-systemd/v22 v22.5.0 github.com/coreos/go-systemd/v22 v22.5.0
github.com/coreos/stream-metadata-go v0.4.2 github.com/coreos/stream-metadata-go v0.4.2
github.com/crc-org/vfkit v0.0.5-0.20230602131541-3d57f09010c9 github.com/crc-org/vfkit v0.0.5-0.20230602131541-3d57f09010c9

12
go.sum
View File

@ -239,10 +239,10 @@ github.com/containernetworking/plugins v0.8.6/go.mod h1:qnw5mN19D8fIwkqW7oHHYDHV
github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8= github.com/containernetworking/plugins v0.9.1/go.mod h1:xP/idU2ldlzN6m4p5LmGiwRDjeJr6FLK6vuiUwoH7P8=
github.com/containernetworking/plugins v1.3.0 h1:QVNXMT6XloyMUoO2wUOqWTC1hWFV62Q6mVDp5H1HnjM= github.com/containernetworking/plugins v1.3.0 h1:QVNXMT6XloyMUoO2wUOqWTC1hWFV62Q6mVDp5H1HnjM=
github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0= github.com/containernetworking/plugins v1.3.0/go.mod h1:Pc2wcedTQQCVuROOOaLBPPxrEXqqXBFt3cZ+/yVg6l0=
github.com/containers/buildah v1.30.1-0.20230504052500-e925b5852e07 h1:Bs2sNFh/fSYr4J6JJLFqzyn3dp6HhlA6ewFwRYUpeIE= github.com/containers/buildah v1.30.1-0.20230627110136-33b7088fec7b h1:cTb0Sxu/tIQ9uPIchFmkYs+uOtylhyO+0h2+i3XzisQ=
github.com/containers/buildah v1.30.1-0.20230504052500-e925b5852e07/go.mod h1:6A/BK0YJLXL8+AqlbceKJrhUT+NtEgsvAc51F7TAllc= github.com/containers/buildah v1.30.1-0.20230627110136-33b7088fec7b/go.mod h1:O2jiDd5+569W8cwqyLnRKiqAHOPTi/Kj+oDlFNsFg24=
github.com/containers/common v0.53.1-0.20230626115555-370c89881624 h1:YBgjfoo0G3tR8vm225ghJnqOZOVv3tH1L1GbyRM9320= github.com/containers/common v0.53.1-0.20230627061926-e6f314e59b81 h1:axB9UaqlBcpVX4yA41OfshJd5emqOuQ/GMNxopyAX20=
github.com/containers/common v0.53.1-0.20230626115555-370c89881624/go.mod h1:qE1MzGl69IoK7ZNCCH51+aLVjyQtnH0LiZe0wG32Jy0= github.com/containers/common v0.53.1-0.20230627061926-e6f314e59b81/go.mod h1:BkgcpfdNC54M3fGDtHUjqt7teGNsuj9yGoWUC+YVhi4=
github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg= github.com/containers/conmon v2.0.20+incompatible h1:YbCVSFSCqFjjVwHTPINGdMX1F6JXHGTUje2ZYobNrkg=
github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I= github.com/containers/conmon v2.0.20+incompatible/go.mod h1:hgwZ2mtuDrppv78a/cOBNiCm6O0UMWGx1mu7P00nu5I=
github.com/containers/image/v5 v5.25.1-0.20230623174242-68798a22ce3e h1:4W/7KRo29f7zRGRruc3kSf18wNZB/loR1jTygi0TvRM= github.com/containers/image/v5 v5.25.1-0.20230623174242-68798a22ce3e h1:4W/7KRo29f7zRGRruc3kSf18wNZB/loR1jTygi0TvRM=
@ -259,8 +259,8 @@ github.com/containers/ocicrypt v1.1.7/go.mod h1:7CAhjcj2H8AYp5YvEie7oVSK2AhBY8Ns
github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY= github.com/containers/psgo v1.8.0 h1:2loGekmGAxM9ir5OsXWEfGwFxorMPYnc6gEDsGFQvhY=
github.com/containers/psgo v1.8.0/go.mod h1:T8ZxnX3Ur4RvnhxFJ7t8xJ1F48RhiZB4rSrOaR/qGHc= github.com/containers/psgo v1.8.0/go.mod h1:T8ZxnX3Ur4RvnhxFJ7t8xJ1F48RhiZB4rSrOaR/qGHc=
github.com/containers/storage v1.43.0/go.mod h1:uZ147thiIFGdVTjMmIw19knttQnUCl3y9zjreHrg11s= github.com/containers/storage v1.43.0/go.mod h1:uZ147thiIFGdVTjMmIw19knttQnUCl3y9zjreHrg11s=
github.com/containers/storage v1.46.2-0.20230621123301-73f29956326d h1:OzN0VtkQ8kcj6HB8QdrIq7qiVsZ6pEcmolV1trZgrgA= github.com/containers/storage v1.47.0 h1:Tl/onL8yE/4QABc2kfPDaTSYijk3QrmXGrO21KXkj58=
github.com/containers/storage v1.46.2-0.20230621123301-73f29956326d/go.mod h1:pRp3lkRo2qodb/ltpnudoXggrviRmaCmU5a5GhTBae0= github.com/containers/storage v1.47.0/go.mod h1:pRp3lkRo2qodb/ltpnudoXggrviRmaCmU5a5GhTBae0=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU= github.com/coreos/go-iptables v0.4.5/go.mod h1:/mVI274lEDI2ns62jHCDnCyBF9Iwsmekav8Dbxlm1MU=

View File

@ -1,28 +0,0 @@
#!/usr/bin/env bash
# This script handles any custom processing of the spec file generated using the `post-upstream-clone`
# action and gets used by the fix-spec-file action in .packit.yaml.
set -eo pipefail
# Get Version from define/types.go in HEAD
VERSION=$(grep ^$'\tVersion' define/types.go | cut -d\" -f2 | sed -e 's/-/~/')
# Generate source tarball from HEAD
git archive --prefix=buildah-$VERSION/ -o buildah-$VERSION.tar.gz HEAD
# RPM Spec modifications
# Use the Version from define/types.go in rpm spec
sed -i "s/^Version:.*/Version: $VERSION/" buildah.spec
# Use Packit's supplied variable in the Release field in rpm spec.
# buildah.spec is generated using `rpkg spec --outdir ./` as mentioned in the
# `post-upstream-clone` action in .packit.yaml.
sed -i "s/^Release:.*/Release: $PACKIT_RPMSPEC_RELEASE%{?dist}/" buildah.spec
# Use above generated tarball as Source in rpm spec
sed -i "s/^Source:.*.tar.gz/Source: buildah-$VERSION.tar.gz/" buildah.spec
# Use the right build dir for autosetup stage in rpm spec
sed -i "s/^%setup.*/%autosetup -Sgit -n %{name}-$VERSION/" buildah.spec

View File

@ -4,8 +4,11 @@
# Build targets can be found at: # Build targets can be found at:
# https://copr.fedorainfracloud.org/coprs/rhcontainerbot/packit-builds/ # https://copr.fedorainfracloud.org/coprs/rhcontainerbot/packit-builds/
# and
# https://copr.fedorainfracloud.org/coprs/rhcontainerbot/podman-next/
specfile_path: buildah.spec specfile_path: rpm/buildah.spec
upstream_tag_template: v{version}
jobs: jobs:
- &copr - &copr
@ -16,15 +19,28 @@ jobs:
enable_net: true enable_net: true
srpm_build_deps: srpm_build_deps:
- make - make
- rpkg
actions:
post-upstream-clone:
- "rpkg spec --outdir ./"
fix-spec-file:
- "bash .packit.sh"
- <<: *copr - <<: *copr
# Run on commit to main branch # Run on commit to main branch
trigger: commit trigger: commit
branch: main branch: main
project: podman-next project: podman-next
- job: propose_downstream
trigger: release
update_release: false
dist_git_branches:
- fedora-all
actions:
pre-sync:
- "bash rpm/update-spec-provides.sh"
- job: koji_build
trigger: commit
dist_git_branches:
- fedora-all
- job: bodhi_update
trigger: commit
dist_git_branches:
- fedora-branched # rawhide updates are created automatically

View File

@ -1,7 +1,7 @@
export GOPROXY=https://proxy.golang.org export GOPROXY=https://proxy.golang.org
APPARMORTAG := $(shell hack/apparmor_tag.sh) APPARMORTAG := $(shell hack/apparmor_tag.sh)
STORAGETAGS := $(shell ./btrfs_tag.sh) $(shell ./btrfs_installed_tag.sh) $(shell ./libdm_tag.sh) $(shell ./hack/libsubid_tag.sh) STORAGETAGS := exclude_graphdriver_devicemapper $(shell ./btrfs_tag.sh) $(shell ./btrfs_installed_tag.sh) $(shell ./hack/libsubid_tag.sh)
SECURITYTAGS ?= seccomp $(APPARMORTAG) SECURITYTAGS ?= seccomp $(APPARMORTAG)
TAGS ?= $(SECURITYTAGS) $(STORAGETAGS) $(shell ./hack/systemd_tag.sh) TAGS ?= $(SECURITYTAGS) $(STORAGETAGS) $(shell ./hack/systemd_tag.sh)
BUILDTAGS += $(TAGS) BUILDTAGS += $(TAGS)
@ -27,7 +27,7 @@ RACEFLAGS := $(shell $(GO_TEST) -race ./pkg/dummy > /dev/null 2>&1 && echo -race
COMMIT_NO ?= $(shell git rev-parse HEAD 2> /dev/null || true) COMMIT_NO ?= $(shell git rev-parse HEAD 2> /dev/null || true)
GIT_COMMIT ?= $(if $(shell git status --porcelain --untracked-files=no),${COMMIT_NO}-dirty,${COMMIT_NO}) GIT_COMMIT ?= $(if $(shell git status --porcelain --untracked-files=no),${COMMIT_NO}-dirty,${COMMIT_NO})
SOURCE_DATE_EPOCH ?= $(if $(shell date +%s),$(shell date +%s),$(error "date failed")) SOURCE_DATE_EPOCH ?= $(if $(shell date +%s),$(shell date +%s),$(error "date failed"))
STATIC_STORAGETAGS = "containers_image_openpgp exclude_graphdriver_devicemapper $(STORAGE_TAGS)" STATIC_STORAGETAGS = "containers_image_openpgp $(STORAGE_TAGS)"
# we get GNU make 3.x in MacOS build envs, which wants # to be escaped in # we get GNU make 3.x in MacOS build envs, which wants # to be escaped in
# strings, while the 4.x we have on Linux doesn't. this is the documented # strings, while the 4.x we have on Linux doesn't. this is the documented

View File

@ -1,165 +0,0 @@
# For automatic rebuilds in COPR
# The following tag is to get correct syntax highlighting for this file in vim text editor
# vim: syntax=spec
# Any additinoal comments should go below this line or else syntax highlighting
# may not work.
# CAUTION: This is not a replacement for RPMs provided by your distro.
# Only intended to build and test the latest unreleased changes.
%global with_debug 1
# RHEL 8's default %%gobuild macro doesn't account for the BUILDTAGS variable, so we
# set it separately here and do not depend on RHEL 8's go-srpm-macros package.
%if !0%{?fedora} && 0%{?rhel} <= 8
%define gobuild(o:) GO111MODULE=off go build -buildmode pie -compiler gc -tags="rpm_crashtraceback libtrust_openssl ${BUILDTAGS:-}" -ldflags "-linkmode=external -compressdwarf=false ${LDFLAGS:-} -B 0x$(head -c20 /dev/urandom|od -An -tx1|tr -d ' \\n') -extldflags '%__global_ldflags'" -a -v -x %{?**};
%endif
%if 0%{?with_debug}
%global _find_debuginfo_dwz_opts %{nil}
%global _dwz_low_mem_die_limit 0
%else
%global debug_package %{nil}
%endif
%global provider github
%global provider_tld com
%global project containers
%global repo %{name}
# https://github.com/containers/%%{name}
%global import_path %{provider}.%{provider_tld}/%{project}/%{repo}
%global git0 https://%{import_path}
Name: {{{ git_dir_name }}}
Epoch: 101
Version: {{{ git_dir_version }}}
Release: 1%{?dist}
Summary: Manage Pods, Containers and Container Images
License: ASL 2.0
URL: https://github.com/containers/buildah
VCS: {{{ git_dir_vcs }}}
Source: {{{ git_dir_pack }}}
BuildRequires: device-mapper-devel
BuildRequires: git-core
BuildRequires: golang
BuildRequires: glib2-devel
BuildRequires: glibc-static
BuildRequires: go-md2man
%if 0%{?fedora} || 0%{?rhel} >= 9
BuildRequires: go-rpm-macros
%endif
BuildRequires: gpgme-devel
BuildRequires: libassuan-devel
BuildRequires: make
BuildRequires: ostree-devel
BuildRequires: shadow-utils-subid-devel
%if 0%{?fedora} && ! 0%{?rhel}
BuildRequires: btrfs-progs-devel
%endif
Requires: containers-common-extra >= 4:1-78
%if 0%{?rhel}
BuildRequires: libseccomp-devel
%else
BuildRequires: libseccomp-static
%endif
Requires: libseccomp
Suggests: cpp
%description
The %{name} package provides a command line tool which can be used to
* create a working container from scratch
or
* create a working container from an image as a starting point
* mount/umount a working container's root file system for manipulation
* save container's root file system layer to create a new image
* delete a working container or an image.
%package tests
Summary: Tests for %{name}
Requires: %{name} = %{version}-%{release}
Requires: bats
Requires: bzip2
Requires: podman
Requires: golang
Requires: jq
Requires: httpd-tools
Requires: openssl
Requires: nmap-ncat
Requires: git-daemon
%description tests
%{summary}
This package contains system tests for %{name}
%prep
{{{ git_dir_setup_macro }}}
%build
%set_build_flags
export GOPATH=$(pwd)/_build:$(pwd)
export CGO_CFLAGS=$CFLAGS
# These extra flags present in $CFLAGS have been skipped for now as they break the build
CGO_CFLAGS=$(echo $CGO_CFLAGS | sed 's/-flto=auto//g')
CGO_CFLAGS=$(echo $CGO_CFLAGS | sed 's/-Wp,D_GLIBCXX_ASSERTIONS//g')
CGO_CFLAGS=$(echo $CGO_CFLAGS | sed 's/-specs=\/usr\/lib\/rpm\/redhat\/redhat-annobin-cc1//g')
%ifarch x86_64
export CGO_CFLAGS+=" -m64 -mtune=generic -fcf-protection=full"
%endif
mkdir _build
pushd _build
mkdir -p src/%{provider}.%{provider_tld}/%{project}
ln -s $(dirs +1 -l) src/%{import_path}
popd
mv vendor src
export CNI_VERSION=`grep '^# github.com/containernetworking/cni ' src/modules.txt | sed 's,.* ,,'`
export LDFLAGS="-X main.buildInfo=`date +%s` -X main.cniVersion=${CNI_VERSION}"
export BUILDTAGS="$(hack/libsubid_tag.sh) seccomp selinux $(hack/systemd_tag.sh)"
%if 0%{?rhel}
export BUILDTAGS="$BUILDTAGS exclude_graphdriver_btrfs btrfs_noversion"
%endif
%gobuild -o bin/%{name} %{import_path}/cmd/%{name}
%gobuild -o bin/imgtype %{import_path}/tests/imgtype
%gobuild -o bin/copy %{import_path}/tests/copy
GOMD2MAN=go-md2man %{__make} -C docs
# This will copy the files generated by the `make` command above into
# the installable rpm package.
%install
export GOPATH=$(pwd)/_build:$(pwd):%{gopath}
make DESTDIR=%{buildroot} PREFIX=%{_prefix} install install.completions
make DESTDIR=%{buildroot} PREFIX=%{_prefix} -C docs install
install -d -p %{buildroot}/%{_datadir}/%{name}/test/system
cp -pav tests/. %{buildroot}/%{_datadir}/%{name}/test/system
cp bin/imgtype %{buildroot}/%{_bindir}/%{name}-imgtype
cp bin/copy %{buildroot}/%{_bindir}/%{name}-copy
rm -f %{buildroot}%{_mandir}/man5/{Containerfile.5*,containerignore.5*}
%files
%license LICENSE
%doc README.md
%{_bindir}/%{name}
%{_mandir}/man1/%{name}*
%dir %{_datadir}/bash-completion
%dir %{_datadir}/bash-completion/completions
%{_datadir}/bash-completion/completions/%{name}
%files tests
%license LICENSE
%{_bindir}/%{name}-imgtype
%{_bindir}/%{name}-copy
%{_datadir}/%{name}/test
%changelog
{{{ git_dir_changelog }}}

View File

@ -501,6 +501,10 @@ func runUsingChroot(spec *specs.Spec, bundlePath string, ctty *os.File, stdin io
// Apologize for the namespace configuration that we're about to ignore. // Apologize for the namespace configuration that we're about to ignore.
logNamespaceDiagnostics(spec) logNamespaceDiagnostics(spec)
// We need to lock the thread so that PR_SET_PDEATHSIG won't trigger if the current thread exits.
runtime.LockOSThread()
defer runtime.UnlockOSThread()
// Start the parent subprocess. // Start the parent subprocess.
cmd := unshare.Command(append([]string{runUsingChrootExecCommand}, spec.Process.Args...)...) cmd := unshare.Command(append([]string{runUsingChrootExecCommand}, spec.Process.Args...)...)
setPdeathsig(cmd.Cmd) setPdeathsig(cmd.Cmd)

View File

@ -1721,7 +1721,7 @@ func copierHandlerPut(bulkReader io.Reader, req request, idMappings *idtools.IDM
// no type flag for sockets // no type flag for sockets
default: default:
return fmt.Errorf("unrecognized Typeflag %c", hdr.Typeflag) return fmt.Errorf("unrecognized Typeflag %c", hdr.Typeflag)
case tar.TypeReg, tar.TypeRegA: case tar.TypeReg:
var written int64 var written int64
written, err = createFile(path, tr) written, err = createFile(path, tr)
// only check the length if there wasn't an error, which we'll // only check the length if there wasn't an error, which we'll

View File

@ -17,6 +17,7 @@ import (
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containers/buildah/define" "github.com/containers/buildah/define"
internalUtil "github.com/containers/buildah/internal/util" internalUtil "github.com/containers/buildah/internal/util"
"github.com/containers/buildah/pkg/parse"
"github.com/containers/buildah/util" "github.com/containers/buildah/util"
"github.com/containers/common/libimage" "github.com/containers/common/libimage"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
@ -65,7 +66,9 @@ func BuildDockerfiles(ctx context.Context, store storage.Store, options define.B
if options.CommonBuildOpts == nil { if options.CommonBuildOpts == nil {
options.CommonBuildOpts = &define.CommonBuildOptions{} options.CommonBuildOpts = &define.CommonBuildOptions{}
} }
if err := parse.Volumes(options.CommonBuildOpts.Volumes); err != nil {
return "", nil, fmt.Errorf("validating volumes: %w", err)
}
if len(paths) == 0 { if len(paths) == 0 {
return "", nil, errors.New("building: no dockerfiles specified") return "", nil, errors.New("building: no dockerfiles specified")
} }

View File

@ -470,34 +470,34 @@ func (b *Executor) buildStage(ctx context.Context, cleanupStages map[int]*StageE
output := "" output := ""
if stageIndex == len(stages)-1 { if stageIndex == len(stages)-1 {
output = b.output output = b.output
} // Check if any labels were passed in via the API, and add a final line
// Check if any labels were passed in via the API, and add a final line // to the Dockerfile that would provide the same result.
// to the Dockerfile that would provide the same result. // Reason: Docker adds label modification as a last step which can be
// Reason: Docker adds label modification as a last step which can be // processed like regular steps, and if no modification is done to
// processed like regular steps, and if no modification is done to // layers, its easier to re-use cached layers.
// layers, its easier to re-use cached layers. if len(b.labels) > 0 {
if len(b.labels) > 0 { var labelLine string
var labelLine string labels := append([]string{}, b.labels...)
labels := append([]string{}, b.labels...) for _, labelSpec := range labels {
for _, labelSpec := range labels { label := strings.SplitN(labelSpec, "=", 2)
label := strings.SplitN(labelSpec, "=", 2) key := label[0]
key := label[0] value := ""
value := "" if len(label) > 1 {
if len(label) > 1 { value = label[1]
value = label[1] }
// check only for an empty key since docker allows empty values
if key != "" {
labelLine += fmt.Sprintf(" %q=%q", key, value)
}
} }
// check only for an empty key since docker allows empty values if len(labelLine) > 0 {
if key != "" { additionalNode, err := imagebuilder.ParseDockerfile(strings.NewReader("LABEL" + labelLine + "\n"))
labelLine += fmt.Sprintf(" %q=%q", key, value) if err != nil {
return "", nil, fmt.Errorf("while adding additional LABEL step: %w", err)
}
stage.Node.Children = append(stage.Node.Children, additionalNode.Children...)
} }
} }
if len(labelLine) > 0 {
additionalNode, err := imagebuilder.ParseDockerfile(strings.NewReader("LABEL" + labelLine + "\n"))
if err != nil {
return "", nil, fmt.Errorf("while adding additional LABEL step: %w", err)
}
stage.Node.Children = append(stage.Node.Children, additionalNode.Children...)
}
} }
// If this stage is starting out with environment variables that were // If this stage is starting out with environment variables that were

View File

@ -161,7 +161,6 @@ Prior to installing Buildah, install the following packages on your Linux distro
* bats * bats
* btrfs-progs-devel * btrfs-progs-devel
* bzip2 * bzip2
* device-mapper-devel
* git * git
* go-md2man * go-md2man
* gpgme-devel * gpgme-devel
@ -181,7 +180,6 @@ In Fedora, you can use this command:
golang \ golang \
bats \ bats \
btrfs-progs-devel \ btrfs-progs-devel \
device-mapper-devel \
glib2-devel \ glib2-devel \
gpgme-devel \ gpgme-devel \
libassuan-devel \ libassuan-devel \
@ -216,7 +214,6 @@ In RHEL and CentOS, run this command to install the build dependencies:
golang \ golang \
bats \ bats \
btrfs-progs-devel \ btrfs-progs-devel \
device-mapper-devel \
glib2-devel \ glib2-devel \
gpgme-devel \ gpgme-devel \
libassuan-devel \ libassuan-devel \
@ -242,7 +239,6 @@ On openSUSE Tumbleweed, install go via `zypper in go`, then run this command:
bzip2 \ bzip2 \
libgpgme-devel \ libgpgme-devel \
libseccomp-devel \ libseccomp-devel \
device-mapper-devel \
libbtrfs-devel \ libbtrfs-devel \
go-md2man go-md2man
``` ```
@ -256,7 +252,7 @@ In Ubuntu jammy you can use these commands:
``` ```
sudo apt-get -y -qq update sudo apt-get -y -qq update
sudo apt-get -y install bats btrfs-progs git libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libseccomp-dev libselinux1-dev skopeo go-md2man make sudo apt-get -y install bats btrfs-progs git libapparmor-dev libglib2.0-dev libgpgme11-dev libseccomp-dev libselinux1-dev skopeo go-md2man make
sudo apt-get -y install golang-1.18 sudo apt-get -y install golang-1.18
``` ```
Then to install Buildah on Ubuntu follow the steps in this example: Then to install Buildah on Ubuntu follow the steps in this example:
@ -282,7 +278,7 @@ sudo gpg --export 0x018BA5AD9DF57A4448F0E6CF8BECF1637AD8C79D >> /usr/share/keyri
sudo echo 'deb [signed-by=/usr/share/keyrings/projectatomic-ppa.gpg] http://ppa.launchpad.net/projectatomic/ppa/ubuntu zesty main' > /etc/apt/sources.list.d/projectatomic-ppa.list sudo echo 'deb [signed-by=/usr/share/keyrings/projectatomic-ppa.gpg] http://ppa.launchpad.net/projectatomic/ppa/ubuntu zesty main' > /etc/apt/sources.list.d/projectatomic-ppa.list
sudo apt update sudo apt update
sudo apt -y install -t stretch-backports golang sudo apt -y install -t stretch-backports golang
sudo apt -y install bats btrfs-tools git libapparmor-dev libdevmapper-dev libglib2.0-dev libgpgme11-dev libseccomp-dev libselinux1-dev skopeo-containers go-md2man sudo apt -y install bats btrfs-tools git libapparmor-dev libglib2.0-dev libgpgme11-dev libseccomp-dev libselinux1-dev skopeo-containers go-md2man
``` ```
The build steps on Debian are otherwise the same as Ubuntu, above. The build steps on Debian are otherwise the same as Ubuntu, above.
@ -319,7 +315,7 @@ cat /etc/containers/registries.conf
# and 'registries.block'. # and 'registries.block'.
[registries.search] [registries.search]
registries = ['docker.io', 'registry.fedoraproject.org', 'quay.io', 'registry.access.redhat.com', 'registry.centos.org'] registries = ['docker.io', 'registry.fedoraproject.org', 'quay.io', 'registry.access.redhat.com']
# If you need to access insecure registries, add the registry's fully-qualified name. # If you need to access insecure registries, add the registry's fully-qualified name.
# An insecure registry is one that does not have a valid SSL certificate or only does HTTP. # An insecure registry is one that does not have a valid SSL certificate or only does HTTP.

View File

@ -8,9 +8,8 @@ import (
"github.com/containers/buildah/define" "github.com/containers/buildah/define"
"github.com/containers/common/libimage" "github.com/containers/common/libimage"
"github.com/containers/common/pkg/config"
"github.com/containers/image/v5/types" "github.com/containers/image/v5/types"
encconfig "github.com/containers/ocicrypt/config"
enchelpers "github.com/containers/ocicrypt/helpers"
"github.com/containers/storage" "github.com/containers/storage"
"github.com/containers/storage/pkg/archive" "github.com/containers/storage/pkg/archive"
"github.com/containers/storage/pkg/chrootarchive" "github.com/containers/storage/pkg/chrootarchive"
@ -56,6 +55,13 @@ func GetTempDir() string {
if tmpdir, ok := os.LookupEnv("TMPDIR"); ok { if tmpdir, ok := os.LookupEnv("TMPDIR"); ok {
return tmpdir return tmpdir
} }
containerConfig, err := config.Default()
if err != nil {
tmpdir, err := containerConfig.ImageCopyTmpDir()
if err != nil {
return tmpdir
}
}
return "/var/tmp" return "/var/tmp"
} }
@ -106,49 +112,3 @@ func ExportFromReader(input io.Reader, opts define.BuildOutputOption) error {
} }
return nil return nil
} }
// DecryptConfig translates decryptionKeys into a DescriptionConfig structure
func DecryptConfig(decryptionKeys []string) (*encconfig.DecryptConfig, error) {
decryptConfig := &encconfig.DecryptConfig{}
if len(decryptionKeys) > 0 {
// decryption
dcc, err := enchelpers.CreateCryptoConfig([]string{}, decryptionKeys)
if err != nil {
return nil, fmt.Errorf("invalid decryption keys: %w", err)
}
cc := encconfig.CombineCryptoConfigs([]encconfig.CryptoConfig{dcc})
decryptConfig = cc.DecryptConfig
}
return decryptConfig, nil
}
// EncryptConfig translates encryptionKeys into a EncriptionsConfig structure
func EncryptConfig(encryptionKeys []string, encryptLayers []int) (*encconfig.EncryptConfig, *[]int, error) {
var encLayers *[]int
var encConfig *encconfig.EncryptConfig
if len(encryptionKeys) > 0 {
// encryption
encLayers = &encryptLayers
ecc, err := enchelpers.CreateCryptoConfig(encryptionKeys, []string{})
if err != nil {
return nil, nil, fmt.Errorf("invalid encryption keys: %w", err)
}
cc := encconfig.CombineCryptoConfigs([]encconfig.CryptoConfig{ecc})
encConfig = cc.EncryptConfig
}
return encConfig, encLayers, nil
}
// GetFormat translates format string into either docker or OCI format constant
func GetFormat(format string) (string, error) {
switch format {
case define.OCI:
return define.OCIv1ImageManifest, nil
case define.DOCKER:
return define.Dockerv2ImageManifest, nil
default:
return "", fmt.Errorf("unrecognized image type %q", format)
}
}

View File

@ -1,15 +0,0 @@
#!/usr/bin/env bash
tmpdir="$PWD/tmp.$RANDOM"
mkdir -p "$tmpdir"
trap 'rm -fr "$tmpdir"' EXIT
${CC:-cc} ${CFLAGS} ${CPPFLAGS} ${LDFLAGS} -o "$tmpdir"/libdm_tag -x c - -ldevmapper > /dev/null 2> /dev/null << EOF
#include <libdevmapper.h>
int main() {
struct dm_task *task;
dm_task_deferred_remove(task);
return 0;
}
EOF
if test $? -ne 0 ; then
echo libdm_no_deferred_remove
fi

View File

@ -14,7 +14,6 @@ import (
"time" "time"
"github.com/containers/buildah/define" "github.com/containers/buildah/define"
iutil "github.com/containers/buildah/internal/util"
"github.com/containers/buildah/pkg/parse" "github.com/containers/buildah/pkg/parse"
"github.com/containers/buildah/pkg/util" "github.com/containers/buildah/pkg/util"
"github.com/containers/common/pkg/auth" "github.com/containers/common/pkg/auth"
@ -135,7 +134,7 @@ func GenBuildOptions(c *cobra.Command, inputArgs []string, iopts BuildOptions) (
} }
containerfiles := getContainerfiles(iopts.File) containerfiles := getContainerfiles(iopts.File)
format, err := iutil.GetFormat(iopts.Format) format, err := GetFormat(iopts.Format)
if err != nil { if err != nil {
return options, nil, nil, err return options, nil, nil, err
} }
@ -272,7 +271,7 @@ func GenBuildOptions(c *cobra.Command, inputArgs []string, iopts BuildOptions) (
return options, nil, nil, err return options, nil, nil, err
} }
decryptConfig, err := iutil.DecryptConfig(iopts.DecryptionKeys) decryptConfig, err := DecryptConfig(iopts.DecryptionKeys)
if err != nil { if err != nil {
return options, nil, nil, fmt.Errorf("unable to obtain decrypt config: %w", err) return options, nil, nil, fmt.Errorf("unable to obtain decrypt config: %w", err)
} }
@ -433,7 +432,7 @@ func readBuildArgFile(buildargfile string, args map[string]string) error {
return err return err
} }
for _, arg := range strings.Split(string(argfile), "\n") { for _, arg := range strings.Split(string(argfile), "\n") {
if len (arg) == 0 || arg[0] == '#' { if len(arg) == 0 || arg[0] == '#' {
continue continue
} }
readBuildArg(arg, args) readBuildArg(arg, args)

View File

@ -15,6 +15,8 @@ import (
"github.com/containers/buildah/pkg/parse" "github.com/containers/buildah/pkg/parse"
commonComp "github.com/containers/common/pkg/completion" commonComp "github.com/containers/common/pkg/completion"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
encconfig "github.com/containers/ocicrypt/config"
enchelpers "github.com/containers/ocicrypt/helpers"
"github.com/containers/storage/pkg/unshare" "github.com/containers/storage/pkg/unshare"
"github.com/opencontainers/runtime-spec/specs-go" "github.com/opencontainers/runtime-spec/specs-go"
"github.com/spf13/pflag" "github.com/spf13/pflag"
@ -523,3 +525,49 @@ func LookupEnvVarReferences(specs, environ []string) []string {
return result return result
} }
// DecryptConfig translates decryptionKeys into a DescriptionConfig structure
func DecryptConfig(decryptionKeys []string) (*encconfig.DecryptConfig, error) {
var decryptConfig *encconfig.DecryptConfig
if len(decryptionKeys) > 0 {
// decryption
dcc, err := enchelpers.CreateCryptoConfig([]string{}, decryptionKeys)
if err != nil {
return nil, fmt.Errorf("invalid decryption keys: %w", err)
}
cc := encconfig.CombineCryptoConfigs([]encconfig.CryptoConfig{dcc})
decryptConfig = cc.DecryptConfig
}
return decryptConfig, nil
}
// EncryptConfig translates encryptionKeys into a EncriptionsConfig structure
func EncryptConfig(encryptionKeys []string, encryptLayers []int) (*encconfig.EncryptConfig, *[]int, error) {
var encLayers *[]int
var encConfig *encconfig.EncryptConfig
if len(encryptionKeys) > 0 {
// encryption
encLayers = &encryptLayers
ecc, err := enchelpers.CreateCryptoConfig(encryptionKeys, []string{})
if err != nil {
return nil, nil, fmt.Errorf("invalid encryption keys: %w", err)
}
cc := encconfig.CombineCryptoConfigs([]encconfig.CryptoConfig{ecc})
encConfig = cc.EncryptConfig
}
return encConfig, encLayers, nil
}
// GetFormat translates format string into either docker or OCI format constant
func GetFormat(format string) (string, error) {
switch format {
case define.OCI:
return define.OCIv1ImageManifest, nil
case define.DOCKER:
return define.Dockerv2ImageManifest, nil
default:
return "", fmt.Errorf("unrecognized image type %q", format)
}
}

View File

@ -17,6 +17,7 @@ import (
"github.com/containerd/containerd/platforms" "github.com/containerd/containerd/platforms"
"github.com/containers/buildah/define" "github.com/containers/buildah/define"
internalParse "github.com/containers/buildah/internal/parse" internalParse "github.com/containers/buildah/internal/parse"
internalUtil "github.com/containers/buildah/internal/util"
"github.com/containers/buildah/pkg/sshagent" "github.com/containers/buildah/pkg/sshagent"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/parse" "github.com/containers/common/pkg/parse"
@ -154,9 +155,6 @@ func CommonBuildOptionsFromFlagSet(flags *pflag.FlagSet, findFlagFunc func(name
return nil, fmt.Errorf("invalid --shm-size: %w", err) return nil, fmt.Errorf("invalid --shm-size: %w", err)
} }
volumes, _ := flags.GetStringArray("volume") volumes, _ := flags.GetStringArray("volume")
if err := Volumes(volumes); err != nil {
return nil, err
}
cpuPeriod, _ := flags.GetUint64("cpu-period") cpuPeriod, _ := flags.GetUint64("cpu-period")
cpuQuota, _ := flags.GetInt64("cpu-quota") cpuQuota, _ := flags.GetInt64("cpu-quota")
cpuShares, _ := flags.GetUint64("cpu-shares") cpuShares, _ := flags.GetUint64("cpu-shares")
@ -999,10 +997,7 @@ func isValidDeviceMode(mode string) bool {
} }
func GetTempDir() string { func GetTempDir() string {
if tmpdir, ok := os.LookupEnv("TMPDIR"); ok { return internalUtil.GetTempDir()
return tmpdir
}
return "/var/tmp"
} }
// Secrets parses the --secret flag // Secrets parses the --secret flag

View File

@ -35,6 +35,7 @@ import (
"github.com/containers/common/libnetwork/network" "github.com/containers/common/libnetwork/network"
"github.com/containers/common/libnetwork/resolvconf" "github.com/containers/common/libnetwork/resolvconf"
netTypes "github.com/containers/common/libnetwork/types" netTypes "github.com/containers/common/libnetwork/types"
netUtil "github.com/containers/common/libnetwork/util"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
"github.com/containers/common/pkg/subscriptions" "github.com/containers/common/pkg/subscriptions"
imageTypes "github.com/containers/image/v5/types" imageTypes "github.com/containers/image/v5/types"
@ -117,7 +118,7 @@ func (b *Builder) addResolvConf(rdir string, chownOpts *idtools.IDPair, dnsServe
} }
// generateHosts creates a containers hosts file // generateHosts creates a containers hosts file
func (b *Builder) generateHosts(rdir string, chownOpts *idtools.IDPair, imageRoot string) (string, error) { func (b *Builder) generateHosts(rdir string, chownOpts *idtools.IDPair, imageRoot string, spec *spec.Spec) (string, error) {
conf, err := config.Default() conf, err := config.Default()
if err != nil { if err != nil {
return "", err return "", err
@ -128,12 +129,34 @@ func (b *Builder) generateHosts(rdir string, chownOpts *idtools.IDPair, imageRoo
return "", err return "", err
} }
var entries etchosts.HostEntries
isHost := true
if spec.Linux != nil {
for _, ns := range spec.Linux.Namespaces {
if ns.Type == specs.NetworkNamespace {
isHost = false
break
}
}
}
// add host entry for local ip when running in host network
if spec.Hostname != "" && isHost {
ip := netUtil.GetLocalIP()
if ip != "" {
entries = append(entries, etchosts.HostEntry{
Names: []string{spec.Hostname},
IP: ip,
})
}
}
targetfile := filepath.Join(rdir, "hosts") targetfile := filepath.Join(rdir, "hosts")
if err := etchosts.New(&etchosts.Params{ if err := etchosts.New(&etchosts.Params{
BaseFile: path, BaseFile: path,
ExtraHosts: b.CommonBuildOpts.AddHost, ExtraHosts: b.CommonBuildOpts.AddHost,
HostContainersInternalIP: etchosts.GetHostContainersInternalIP(conf, nil, nil), HostContainersInternalIP: etchosts.GetHostContainersInternalIP(conf, nil, nil),
TargetFile: targetfile, TargetFile: targetfile,
ContainerIPs: entries,
}); err != nil { }); err != nil {
return "", err return "", err
} }
@ -368,6 +391,9 @@ func checkAndOverrideIsolationOptions(isolation define.Isolation, options *RunOp
if (pidns != nil && pidns.Host) && (userns != nil && !userns.Host) { if (pidns != nil && pidns.Host) && (userns != nil && !userns.Host) {
return fmt.Errorf("not allowed to mix host PID namespace with container user namespace") return fmt.Errorf("not allowed to mix host PID namespace with container user namespace")
} }
case IsolationChroot:
logrus.Info("network namespace isolation not supported with chroot isolation, forcing host network")
options.NamespaceOptions.AddOrReplace(define.NamespaceOption{Name: string(specs.NetworkNamespace), Host: true})
} }
return nil return nil
} }
@ -1105,8 +1131,12 @@ func runUsingRuntimeMain() {
os.Exit(1) os.Exit(1)
} }
func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options RunOptions, configureNetwork bool, configureNetworks, func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options RunOptions, configureNetwork bool, networkString string,
moreCreateArgs []string, spec *specs.Spec, rootPath, bundlePath, containerName, buildContainerName, hostsFile string) (err error) { moreCreateArgs []string, spec *specs.Spec, rootPath, bundlePath, containerName, buildContainerName, hostsFile string) (err error) {
// Lock the caller to a single OS-level thread.
runtime.LockOSThread()
defer runtime.UnlockOSThread()
var confwg sync.WaitGroup var confwg sync.WaitGroup
config, conferr := json.Marshal(runUsingRuntimeSubprocOptions{ config, conferr := json.Marshal(runUsingRuntimeSubprocOptions{
Options: options, Options: options,
@ -1207,7 +1237,7 @@ func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options Run
return fmt.Errorf("parsing pid %s as a number: %w", string(pidValue), err) return fmt.Errorf("parsing pid %s as a number: %w", string(pidValue), err)
} }
teardown, netstatus, err := b.runConfigureNetwork(pid, isolation, options, configureNetworks, containerName) teardown, netstatus, err := b.runConfigureNetwork(pid, isolation, options, networkString, containerName)
if teardown != nil { if teardown != nil {
defer teardown() defer teardown()
} }
@ -1217,13 +1247,7 @@ func (b *Builder) runUsingRuntimeSubproc(isolation define.Isolation, options Run
// only add hosts if we manage the hosts file // only add hosts if we manage the hosts file
if hostsFile != "" { if hostsFile != "" {
var entries etchosts.HostEntries entries := etchosts.GetNetworkHostEntries(netstatus, spec.Hostname, buildContainerName)
if netstatus != nil {
entries = etchosts.GetNetworkHostEntries(netstatus, spec.Hostname, buildContainerName)
} else {
// we have slirp4netns, default to slirp4netns ip since this is not configurable in buildah
entries = etchosts.HostEntries{{IP: "10.0.2.100", Names: []string{spec.Hostname, buildContainerName}}}
}
// make sure to sync this with (b *Builder) generateHosts() // make sure to sync this with (b *Builder) generateHosts()
err = etchosts.Add(hostsFile, entries) err = etchosts.Add(hostsFile, entries)
if err != nil { if err != nil {
@ -1328,7 +1352,7 @@ func (b *Builder) setupMounts(mountPoint string, spec *specs.Spec, bundlePath st
processGID: int(processGID), processGID: int(processGID),
} }
// Get the list of mounts that are just for this Run() call. // Get the list of mounts that are just for this Run() call.
runMounts, mountArtifacts, err := b.runSetupRunMounts(runFileMounts, runMountInfo, idMaps) runMounts, mountArtifacts, err := b.runSetupRunMounts(mountPoint, runFileMounts, runMountInfo, idMaps)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -1464,10 +1488,28 @@ func cleanableDestinationListFromMounts(mounts []spec.Mount) []string {
return mountDest return mountDest
} }
func checkIfMountDestinationPreExists(root string, dest string) (bool, error) {
statResults, err := copier.Stat(root, "", copier.StatOptions{}, []string{dest})
if err != nil {
return false, err
}
if len(statResults) > 0 {
// We created exact path for globbing so it will
// return only one result.
if statResults[0].Error != "" && len(statResults[0].Globbed) == 0 {
// Path do not exsits.
return false, nil
}
// Path exists.
return true, nil
}
return false, nil
}
// runSetupRunMounts sets up mounts that exist only in this RUN, not in subsequent runs // runSetupRunMounts sets up mounts that exist only in this RUN, not in subsequent runs
// //
// If this function succeeds, the caller must unlock runMountArtifacts.TargetLocks (when??) // If this function succeeds, the caller must unlock runMountArtifacts.TargetLocks (when??)
func (b *Builder) runSetupRunMounts(mounts []string, sources runMountInfo, idMaps IDMaps) ([]spec.Mount, *runMountArtifacts, error) { func (b *Builder) runSetupRunMounts(mountPoint string, mounts []string, sources runMountInfo, idMaps IDMaps) ([]spec.Mount, *runMountArtifacts, error) {
// If `type` is not set default to TypeBind // If `type` is not set default to TypeBind
mountType := define.TypeBind mountType := define.TypeBind
mountTargets := make([]string, 0, 10) mountTargets := make([]string, 0, 10)
@ -1485,6 +1527,11 @@ func (b *Builder) runSetupRunMounts(mounts []string, sources runMountInfo, idMap
} }
}() }()
for _, mount := range mounts { for _, mount := range mounts {
var mountSpec *spec.Mount
var err error
var envFile, image string
var agent *sshagent.AgentServer
var tl *lockfile.LockFile
tokens := strings.Split(mount, ",") tokens := strings.Split(mount, ",")
for _, field := range tokens { for _, field := range tokens {
if strings.HasPrefix(field, "type=") { if strings.HasPrefix(field, "type=") {
@ -1497,63 +1544,71 @@ func (b *Builder) runSetupRunMounts(mounts []string, sources runMountInfo, idMap
} }
switch mountType { switch mountType {
case "secret": case "secret":
mount, envFile, err := b.getSecretMount(tokens, sources.Secrets, idMaps, sources.WorkDir) mountSpec, envFile, err = b.getSecretMount(tokens, sources.Secrets, idMaps, sources.WorkDir)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if mount != nil { if mountSpec != nil {
finalMounts = append(finalMounts, *mount) finalMounts = append(finalMounts, *mountSpec)
mountTargets = append(mountTargets, mount.Destination)
if envFile != "" { if envFile != "" {
tmpFiles = append(tmpFiles, envFile) tmpFiles = append(tmpFiles, envFile)
} }
} }
case "ssh": case "ssh":
mount, agent, err := b.getSSHMount(tokens, sshCount, sources.SSHSources, idMaps) mountSpec, agent, err = b.getSSHMount(tokens, sshCount, sources.SSHSources, idMaps)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
if mount != nil { if mountSpec != nil {
finalMounts = append(finalMounts, *mount) finalMounts = append(finalMounts, *mountSpec)
mountTargets = append(mountTargets, mount.Destination)
agents = append(agents, agent) agents = append(agents, agent)
if sshCount == 0 { if sshCount == 0 {
defaultSSHSock = mount.Destination defaultSSHSock = mountSpec.Destination
} }
// Count is needed as the default destination of the ssh sock inside the container is /run/buildkit/ssh_agent.{i} // Count is needed as the default destination of the ssh sock inside the container is /run/buildkit/ssh_agent.{i}
sshCount++ sshCount++
} }
case define.TypeBind: case define.TypeBind:
mount, image, err := b.getBindMount(tokens, sources.SystemContext, sources.ContextDir, sources.StageMountPoints, idMaps, sources.WorkDir) mountSpec, image, err = b.getBindMount(tokens, sources.SystemContext, sources.ContextDir, sources.StageMountPoints, idMaps, sources.WorkDir)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
finalMounts = append(finalMounts, *mount) finalMounts = append(finalMounts, *mountSpec)
mountTargets = append(mountTargets, mount.Destination)
// only perform cleanup if image was mounted ignore everything else // only perform cleanup if image was mounted ignore everything else
if image != "" { if image != "" {
mountImages = append(mountImages, image) mountImages = append(mountImages, image)
} }
case "tmpfs": case "tmpfs":
mount, err := b.getTmpfsMount(tokens, idMaps) mountSpec, err = b.getTmpfsMount(tokens, idMaps)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
finalMounts = append(finalMounts, *mount) finalMounts = append(finalMounts, *mountSpec)
mountTargets = append(mountTargets, mount.Destination)
case "cache": case "cache":
mount, tl, err := b.getCacheMount(tokens, sources.StageMountPoints, idMaps, sources.WorkDir) mountSpec, tl, err = b.getCacheMount(tokens, sources.StageMountPoints, idMaps, sources.WorkDir)
if err != nil { if err != nil {
return nil, nil, err return nil, nil, err
} }
finalMounts = append(finalMounts, *mount) finalMounts = append(finalMounts, *mountSpec)
mountTargets = append(mountTargets, mount.Destination)
if tl != nil { if tl != nil {
targetLocks = append(targetLocks, tl) targetLocks = append(targetLocks, tl)
} }
default: default:
return nil, nil, fmt.Errorf("invalid mount type %q", mountType) return nil, nil, fmt.Errorf("invalid mount type %q", mountType)
} }
if mountSpec != nil {
pathPreExists, err := checkIfMountDestinationPreExists(mountPoint, mountSpec.Destination)
if err != nil {
return nil, nil, err
}
if !pathPreExists {
// In such case it means that the path did not exists before
// creating any new mounts therefore we must clean the newly
// created directory after this step.
mountTargets = append(mountTargets, mountSpec.Destination)
}
}
} }
succeeded = true succeeded = true
artifacts := &runMountArtifacts{ artifacts := &runMountArtifacts{
@ -1622,9 +1677,12 @@ func (b *Builder) getSecretMount(tokens []string, secrets map[string]define.Secr
target = filepath.Join(workdir, target) target = filepath.Join(workdir, target)
} }
case "required": case "required":
required, err = strconv.ParseBool(kv[1]) required = true
if err != nil { if len(kv) > 1 {
return nil, "", errInvalidSyntax required, err = strconv.ParseBool(kv[1])
if err != nil {
return nil, "", errInvalidSyntax
}
} }
case "mode": case "mode":
mode64, err := strconv.ParseUint(kv[1], 8, 32) mode64, err := strconv.ParseUint(kv[1], 8, 32)
@ -1876,7 +1934,6 @@ func (b *Builder) cleanupRunMounts(context *imageTypes.SystemContext, mountpoint
return err return err
} }
} }
opts := copier.RemoveOptions{ opts := copier.RemoveOptions{
All: true, All: true,
} }
@ -1900,3 +1957,13 @@ func (b *Builder) cleanupRunMounts(context *imageTypes.SystemContext, mountpoint
internalParse.UnlockLockArray(artifacts.TargetLocks) internalParse.UnlockLockArray(artifacts.TargetLocks)
return prevErr return prevErr
} }
// setPdeathsig sets a parent-death signal for the process
// the goroutine that starts the child process should lock itself to
// a native thread using runtime.LockOSThread() until the child exits
func setPdeathsig(cmd *exec.Cmd) {
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.SysProcAttr.Pdeathsig = syscall.SIGKILL
}

View File

@ -7,10 +7,8 @@ import (
"errors" "errors"
"fmt" "fmt"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"strings" "strings"
"syscall"
"unsafe" "unsafe"
"github.com/containers/buildah/bind" "github.com/containers/buildah/bind"
@ -147,7 +145,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
setupTerminal(g, options.Terminal, options.TerminalSize) setupTerminal(g, options.Terminal, options.TerminalSize)
configureNetwork, configureNetworks, err := b.configureNamespaces(g, &options) configureNetwork, networkString, err := b.configureNamespaces(g, &options)
if err != nil { if err != nil {
return err return err
} }
@ -198,7 +196,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
hostFile := "" hostFile := ""
if !options.NoHosts && !contains(volumes, config.DefaultHostsFile) && options.ConfigureNetwork != define.NetworkDisabled { if !options.NoHosts && !contains(volumes, config.DefaultHostsFile) && options.ConfigureNetwork != define.NetworkDisabled {
hostFile, err = b.generateHosts(path, rootIDPair, mountPoint) hostFile, err = b.generateHosts(path, rootIDPair, mountPoint, spec)
if err != nil { if err != nil {
return err return err
} }
@ -282,7 +280,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
} else { } else {
moreCreateArgs = nil moreCreateArgs = nil
} }
err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, configureNetworks, moreCreateArgs, spec, mountPoint, path, containerName, b.Container, hostFile) err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, networkString, moreCreateArgs, spec, mountPoint, path, containerName, b.Container, hostFile)
case IsolationChroot: case IsolationChroot:
err = chroot.RunUsingChroot(spec, path, homeDir, options.Stdin, options.Stdout, options.Stderr) err = chroot.RunUsingChroot(spec, path, homeDir, options.Stdin, options.Stdout, options.Stderr)
default: default:
@ -376,11 +374,16 @@ func setupCapabilities(g *generate.Generator, defaultCapabilities, adds, drops [
return nil return nil
} }
func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, options RunOptions, configureNetworks []string, containerName string) (teardown func(), netStatus map[string]nettypes.StatusBlock, err error) { func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, options RunOptions, networkString string, containerName string) (teardown func(), netStatus map[string]nettypes.StatusBlock, err error) {
//if isolation == IsolationOCIRootless { //if isolation == IsolationOCIRootless {
//return setupRootlessNetwork(pid) //return setupRootlessNetwork(pid)
//} //}
var configureNetworks []string
if len(networkString) > 0 {
configureNetworks = strings.Split(networkString, ",")
}
if len(configureNetworks) == 0 { if len(configureNetworks) == 0 {
configureNetworks = []string{b.NetworkInterface.DefaultNetworkName()} configureNetworks = []string{b.NetworkInterface.DefaultNetworkName()}
} }
@ -415,7 +418,7 @@ func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, optio
return teardown, nil, nil return teardown, nil, nil
} }
func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOptions define.NamespaceOptions, idmapOptions define.IDMappingOptions, policy define.NetworkConfigurationPolicy) (configureNetwork bool, configureNetworks []string, configureUTS bool, err error) { func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOptions define.NamespaceOptions, idmapOptions define.IDMappingOptions, policy define.NetworkConfigurationPolicy) (configureNetwork bool, networkString string, configureUTS bool, err error) {
// Set namespace options in the container configuration. // Set namespace options in the container configuration.
for _, namespaceOption := range namespaceOptions { for _, namespaceOption := range namespaceOptions {
switch namespaceOption.Name { switch namespaceOption.Name {
@ -423,7 +426,7 @@ func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOpti
configureNetwork = false configureNetwork = false
if !namespaceOption.Host && (namespaceOption.Path == "" || !filepath.IsAbs(namespaceOption.Path)) { if !namespaceOption.Host && (namespaceOption.Path == "" || !filepath.IsAbs(namespaceOption.Path)) {
if namespaceOption.Path != "" && !filepath.IsAbs(namespaceOption.Path) { if namespaceOption.Path != "" && !filepath.IsAbs(namespaceOption.Path) {
configureNetworks = strings.Split(namespaceOption.Path, ",") networkString = namespaceOption.Path
namespaceOption.Path = "" namespaceOption.Path = ""
} }
configureNetwork = (policy != define.NetworkDisabled) configureNetwork = (policy != define.NetworkDisabled)
@ -439,13 +442,13 @@ func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOpti
// equivalents for UTS and and network namespaces. // equivalents for UTS and and network namespaces.
} }
return configureNetwork, configureNetworks, configureUTS, nil return configureNetwork, networkString, configureUTS, nil
} }
func (b *Builder) configureNamespaces(g *generate.Generator, options *RunOptions) (bool, []string, error) { func (b *Builder) configureNamespaces(g *generate.Generator, options *RunOptions) (bool, string, error) {
defaultNamespaceOptions, err := DefaultNamespaceOptions() defaultNamespaceOptions, err := DefaultNamespaceOptions()
if err != nil { if err != nil {
return false, nil, err return false, "", err
} }
namespaceOptions := defaultNamespaceOptions namespaceOptions := defaultNamespaceOptions
@ -466,9 +469,9 @@ func (b *Builder) configureNamespaces(g *generate.Generator, options *RunOptions
} }
} }
configureNetwork, configureNetworks, configureUTS, err := setupNamespaces(options.Logger, g, namespaceOptions, b.IDMappingOptions, networkPolicy) configureNetwork, networkString, configureUTS, err := setupNamespaces(options.Logger, g, namespaceOptions, b.IDMappingOptions, networkPolicy)
if err != nil { if err != nil {
return false, nil, err return false, "", err
} }
if configureUTS { if configureUTS {
@ -495,7 +498,7 @@ func (b *Builder) configureNamespaces(g *generate.Generator, options *RunOptions
spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("HOSTNAME=%s", spec.Hostname)) spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("HOSTNAME=%s", spec.Hostname))
} }
return configureNetwork, configureNetworks, nil return configureNetwork, networkString, nil
} }
func runSetupBoundFiles(bundlePath string, bindFiles map[string]string) (mounts []specs.Mount) { func runSetupBoundFiles(bundlePath string, bindFiles map[string]string) (mounts []specs.Mount) {
@ -531,14 +534,6 @@ func addRlimits(ulimit []string, g *generate.Generator, defaultUlimits []string)
return nil return nil
} }
// setPdeathsig sets a parent-death signal for the process
func setPdeathsig(cmd *exec.Cmd) {
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.SysProcAttr.Pdeathsig = syscall.SIGKILL
}
// Create pipes to use for relaying stdio. // Create pipes to use for relaying stdio.
func runMakeStdioPipe(uid, gid int) ([][]int, error) { func runMakeStdioPipe(uid, gid int) ([][]int, error) {
stdioPipe := make([][]int, 3) stdioPipe := make([][]int, 3)

View File

@ -7,14 +7,13 @@ import (
"context" "context"
"errors" "errors"
"fmt" "fmt"
"net"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"strconv"
"strings" "strings"
"syscall" "syscall"
"time"
"github.com/containernetworking/plugins/pkg/ns"
"github.com/containers/buildah/bind" "github.com/containers/buildah/bind"
"github.com/containers/buildah/chroot" "github.com/containers/buildah/chroot"
"github.com/containers/buildah/copier" "github.com/containers/buildah/copier"
@ -24,8 +23,11 @@ import (
"github.com/containers/buildah/pkg/overlay" "github.com/containers/buildah/pkg/overlay"
"github.com/containers/buildah/pkg/parse" "github.com/containers/buildah/pkg/parse"
"github.com/containers/buildah/util" "github.com/containers/buildah/util"
"github.com/containers/common/libnetwork/pasta"
"github.com/containers/common/libnetwork/resolvconf" "github.com/containers/common/libnetwork/resolvconf"
"github.com/containers/common/libnetwork/slirp4netns"
nettypes "github.com/containers/common/libnetwork/types" nettypes "github.com/containers/common/libnetwork/types"
netUtil "github.com/containers/common/libnetwork/util"
"github.com/containers/common/pkg/capabilities" "github.com/containers/common/pkg/capabilities"
"github.com/containers/common/pkg/chown" "github.com/containers/common/pkg/chown"
"github.com/containers/common/pkg/config" "github.com/containers/common/pkg/config"
@ -202,16 +204,11 @@ func (b *Builder) Run(command []string, options RunOptions) error {
setupTerminal(g, options.Terminal, options.TerminalSize) setupTerminal(g, options.Terminal, options.TerminalSize)
configureNetwork, configureNetworks, err := b.configureNamespaces(g, &options) configureNetwork, networkString, err := b.configureNamespaces(g, &options)
if err != nil { if err != nil {
return err return err
} }
// rootless and networks are not supported
if len(configureNetworks) > 0 && isolation == IsolationOCIRootless {
return errors.New("cannot use networks as rootless")
}
homeDir, err := b.configureUIDGID(g, mountPoint, options) homeDir, err := b.configureUIDGID(g, mountPoint, options)
if err != nil { if err != nil {
return err return err
@ -264,7 +261,7 @@ func (b *Builder) Run(command []string, options RunOptions) error {
hostFile := "" hostFile := ""
if !options.NoHosts && !contains(volumes, config.DefaultHostsFile) && options.ConfigureNetwork != define.NetworkDisabled { if !options.NoHosts && !contains(volumes, config.DefaultHostsFile) && options.ConfigureNetwork != define.NetworkDisabled {
hostFile, err = b.generateHosts(path, rootIDPair, mountPoint) hostFile, err = b.generateHosts(path, rootIDPair, mountPoint, spec)
if err != nil { if err != nil {
return err return err
} }
@ -366,7 +363,7 @@ rootless=%d
if options.NoPivot { if options.NoPivot {
moreCreateArgs = append(moreCreateArgs, "--no-pivot") moreCreateArgs = append(moreCreateArgs, "--no-pivot")
} }
err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, configureNetworks, moreCreateArgs, spec, err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, networkString, moreCreateArgs, spec,
mountPoint, path, define.Package+"-"+filepath.Base(path), b.Container, hostFile) mountPoint, path, define.Package+"-"+filepath.Base(path), b.Container, hostFile)
case IsolationChroot: case IsolationChroot:
err = chroot.RunUsingChroot(spec, path, homeDir, options.Stdin, options.Stdout, options.Stderr) err = chroot.RunUsingChroot(spec, path, homeDir, options.Stdin, options.Stdout, options.Stderr)
@ -375,7 +372,7 @@ rootless=%d
if options.NoPivot { if options.NoPivot {
moreCreateArgs = append(moreCreateArgs, "--no-pivot") moreCreateArgs = append(moreCreateArgs, "--no-pivot")
} }
err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, configureNetworks, moreCreateArgs, spec, err = b.runUsingRuntimeSubproc(isolation, options, configureNetwork, networkString, moreCreateArgs, spec,
mountPoint, path, define.Package+"-"+filepath.Base(path), b.Container, hostFile) mountPoint, path, define.Package+"-"+filepath.Base(path), b.Container, hostFile)
default: default:
err = errors.New("don't know how to run this command") err = errors.New("don't know how to run this command")
@ -420,7 +417,7 @@ func (b *Builder) setupOCIHooks(config *spec.Spec, hasVolumes bool) (map[string]
} }
} }
hookErr, err := hooksExec.RuntimeConfigFilter(context.Background(), allHooks["precreate"], config, hooksExec.DefaultPostKillTimeout) hookErr, err := hooksExec.RuntimeConfigFilter(context.Background(), allHooks["precreate"], config, hooksExec.DefaultPostKillTimeout) //nolint:staticcheck
if err != nil { if err != nil {
logrus.Warnf("Container: precreate hook: %v", err) logrus.Warnf("Container: precreate hook: %v", err)
if hookErr != nil && hookErr != err { if hookErr != nil && hookErr != err {
@ -475,80 +472,122 @@ func addCommonOptsToSpec(commonOpts *define.CommonBuildOptions, g *generate.Gene
return nil return nil
} }
func setupRootlessNetwork(pid int) (teardown func(), err error) { func setupSlirp4netnsNetwork(netns, cid string, options []string) (func(), map[string]nettypes.StatusBlock, error) {
slirp4netns, err := exec.LookPath("slirp4netns") defConfig, err := config.Default()
if err != nil { if err != nil {
return nil, err return nil, nil, fmt.Errorf("failed to get container config: %w", err)
} }
// we need the TmpDir for the slirp4netns code
rootlessSlirpSyncR, rootlessSlirpSyncW, err := os.Pipe() if err := os.MkdirAll(defConfig.Engine.TmpDir, 0o751); err != nil {
return nil, nil, fmt.Errorf("failed to create tempdir: %w", err)
}
res, err := slirp4netns.Setup(&slirp4netns.SetupOptions{
Config: defConfig,
ContainerID: cid,
Netns: netns,
ExtraOptions: options,
Pdeathsig: syscall.SIGKILL,
})
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot create slirp4netns sync pipe: %w", err) return nil, nil, err
} }
defer rootlessSlirpSyncR.Close()
// Be sure there are no fds inherited to slirp4netns except the sync pipe ip, err := slirp4netns.GetIP(res.Subnet)
files, err := os.ReadDir("/proc/self/fd")
if err != nil { if err != nil {
return nil, fmt.Errorf("cannot list open fds: %w", err) return nil, nil, fmt.Errorf("get slirp4netns ip: %w", err)
}
for _, f := range files {
fd, err := strconv.Atoi(f.Name())
if err != nil {
return nil, fmt.Errorf("cannot parse fd: %w", err)
}
if fd == int(rootlessSlirpSyncW.Fd()) {
continue
}
unix.CloseOnExec(fd)
} }
cmd := exec.Command(slirp4netns, "--mtu", "65520", "-r", "3", "-c", strconv.Itoa(pid), "tap0") // create fake status to make sure we get the correct ip in hosts
setPdeathsig(cmd) subnet := nettypes.IPNet{IPNet: net.IPNet{
cmd.Stdin, cmd.Stdout, cmd.Stderr = nil, nil, nil IP: *ip,
cmd.ExtraFiles = []*os.File{rootlessSlirpSyncW} Mask: res.Subnet.Mask,
}}
err = cmd.Start() netStatus := map[string]nettypes.StatusBlock{
rootlessSlirpSyncW.Close() slirp4netns.BinaryName: nettypes.StatusBlock{
if err != nil { Interfaces: map[string]nettypes.NetInterface{
return nil, fmt.Errorf("cannot start slirp4netns: %w", err) "tap0": {
} Subnets: []nettypes.NetAddress{{IPNet: subnet}},
},
b := make([]byte, 1) },
for { },
if err := rootlessSlirpSyncR.SetDeadline(time.Now().Add(1 * time.Second)); err != nil {
return nil, fmt.Errorf("setting slirp4netns pipe timeout: %w", err)
}
if _, err := rootlessSlirpSyncR.Read(b); err == nil {
break
} else {
if os.IsTimeout(err) {
// Check if the process is still running.
var status syscall.WaitStatus
_, err := syscall.Wait4(cmd.Process.Pid, &status, syscall.WNOHANG, nil)
if err != nil {
return nil, fmt.Errorf("failed to read slirp4netns process status: %w", err)
}
if status.Exited() || status.Signaled() {
return nil, errors.New("slirp4netns failed")
}
continue
}
return nil, fmt.Errorf("failed to read from slirp4netns sync pipe: %w", err)
}
} }
return func() { return func() {
cmd.Process.Kill() // nolint:errcheck syscall.Kill(res.Pid, syscall.SIGKILL) // nolint:errcheck
cmd.Wait() // nolint:errcheck var status syscall.WaitStatus
}, nil syscall.Wait4(res.Pid, &status, 0, nil) // nolint:errcheck
}, netStatus, nil
} }
func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, options RunOptions, configureNetworks []string, containerName string) (teardown func(), netStatus map[string]nettypes.StatusBlock, err error) { func setupPasta(netns string, options []string) (func(), map[string]nettypes.StatusBlock, error) {
defConfig, err := config.Default()
if err != nil {
return nil, nil, fmt.Errorf("failed to get container config: %w", err)
}
err = pasta.Setup(&pasta.SetupOptions{
Config: defConfig,
Netns: netns,
ExtraOptions: options,
})
if err != nil {
return nil, nil, err
}
var ip string
err = ns.WithNetNSPath(netns, func(_ ns.NetNS) error {
// get the first ip in the netns and use this as our ip for /etc/hosts
ip = netUtil.GetLocalIP()
return nil
})
if err != nil {
return nil, nil, err
}
// create fake status to make sure we get the correct ip in hosts
subnet := nettypes.IPNet{IPNet: net.IPNet{
IP: net.ParseIP(ip),
Mask: net.IPv4Mask(255, 255, 255, 0),
}}
netStatus := map[string]nettypes.StatusBlock{
slirp4netns.BinaryName: nettypes.StatusBlock{
Interfaces: map[string]nettypes.NetInterface{
"tap0": {
Subnets: []nettypes.NetAddress{{IPNet: subnet}},
},
},
},
}
return nil, netStatus, nil
}
func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, options RunOptions, network, containerName string) (teardown func(), netStatus map[string]nettypes.StatusBlock, err error) {
netns := fmt.Sprintf("/proc/%d/ns/net", pid)
var configureNetworks []string
name, networkOpts, hasOpts := strings.Cut(network, ":")
var netOpts []string
if hasOpts {
netOpts = strings.Split(networkOpts, ",")
}
switch {
case name == slirp4netns.BinaryName,
isolation == IsolationOCIRootless && name == "":
return setupSlirp4netnsNetwork(netns, containerName, netOpts)
case name == pasta.BinaryName:
return setupPasta(netns, netOpts)
// Basically default case except we make sure to not split an empty
// name as this would return a slice with one empty string which is
// not a valid network name.
case len(network) > 0:
// old syntax allow comma separated network names
configureNetworks = strings.Split(network, ",")
}
if isolation == IsolationOCIRootless { if isolation == IsolationOCIRootless {
teardown, err = setupRootlessNetwork(pid) return nil, nil, errors.New("cannot use networks as rootless")
return teardown, nil, err
} }
if len(configureNetworks) == 0 { if len(configureNetworks) == 0 {
@ -560,7 +599,6 @@ func (b *Builder) runConfigureNetwork(pid int, isolation define.Isolation, optio
// interfaces. Ensure this by opening a handle to the network // interfaces. Ensure this by opening a handle to the network
// namespace, and using our copy to both configure and // namespace, and using our copy to both configure and
// deconfigure it. // deconfigure it.
netns := fmt.Sprintf("/proc/%d/ns/net", pid)
netFD, err := unix.Open(netns, unix.O_RDONLY, 0) netFD, err := unix.Open(netns, unix.O_RDONLY, 0)
if err != nil { if err != nil {
return nil, nil, fmt.Errorf("opening network namespace: %w", err) return nil, nil, fmt.Errorf("opening network namespace: %w", err)
@ -615,10 +653,10 @@ func runMakeStdioPipe(uid, gid int) ([][]int, error) {
return stdioPipe, nil return stdioPipe, nil
} }
func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOptions define.NamespaceOptions, idmapOptions define.IDMappingOptions, policy define.NetworkConfigurationPolicy) (configureNetwork bool, configureNetworks []string, configureUTS bool, err error) { func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOptions define.NamespaceOptions, idmapOptions define.IDMappingOptions, policy define.NetworkConfigurationPolicy) (configureNetwork bool, networkString string, configureUTS bool, err error) {
defaultContainerConfig, err := config.Default() defaultContainerConfig, err := config.Default()
if err != nil { if err != nil {
return false, nil, false, fmt.Errorf("failed to get container config: %w", err) return false, "", false, fmt.Errorf("failed to get container config: %w", err)
} }
addSysctl := func(prefixes []string) error { addSysctl := func(prefixes []string) error {
@ -644,7 +682,7 @@ func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOpti
case string(specs.IPCNamespace): case string(specs.IPCNamespace):
if !namespaceOption.Host { if !namespaceOption.Host {
if err := addSysctl([]string{"fs.mqueue"}); err != nil { if err := addSysctl([]string{"fs.mqueue"}); err != nil {
return false, nil, false, err return false, "", false, err
} }
} }
case string(specs.UserNamespace): case string(specs.UserNamespace):
@ -657,7 +695,7 @@ func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOpti
configureNetwork = false configureNetwork = false
if !namespaceOption.Host && (namespaceOption.Path == "" || !filepath.IsAbs(namespaceOption.Path)) { if !namespaceOption.Host && (namespaceOption.Path == "" || !filepath.IsAbs(namespaceOption.Path)) {
if namespaceOption.Path != "" && !filepath.IsAbs(namespaceOption.Path) { if namespaceOption.Path != "" && !filepath.IsAbs(namespaceOption.Path) {
configureNetworks = strings.Split(namespaceOption.Path, ",") networkString = namespaceOption.Path
namespaceOption.Path = "" namespaceOption.Path = ""
} }
configureNetwork = (policy != define.NetworkDisabled) configureNetwork = (policy != define.NetworkDisabled)
@ -669,30 +707,30 @@ func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOpti
configureUTS = true configureUTS = true
} }
if err := addSysctl([]string{"kernel.hostname", "kernel.domainame"}); err != nil { if err := addSysctl([]string{"kernel.hostname", "kernel.domainame"}); err != nil {
return false, nil, false, err return false, "", false, err
} }
} }
} }
if namespaceOption.Host { if namespaceOption.Host {
if err := g.RemoveLinuxNamespace(namespaceOption.Name); err != nil { if err := g.RemoveLinuxNamespace(namespaceOption.Name); err != nil {
return false, nil, false, fmt.Errorf("removing %q namespace for run: %w", namespaceOption.Name, err) return false, "", false, fmt.Errorf("removing %q namespace for run: %w", namespaceOption.Name, err)
} }
} else if err := g.AddOrReplaceLinuxNamespace(namespaceOption.Name, namespaceOption.Path); err != nil { } else if err := g.AddOrReplaceLinuxNamespace(namespaceOption.Name, namespaceOption.Path); err != nil {
if namespaceOption.Path == "" { if namespaceOption.Path == "" {
return false, nil, false, fmt.Errorf("adding new %q namespace for run: %w", namespaceOption.Name, err) return false, "", false, fmt.Errorf("adding new %q namespace for run: %w", namespaceOption.Name, err)
} }
return false, nil, false, fmt.Errorf("adding %q namespace %q for run: %w", namespaceOption.Name, namespaceOption.Path, err) return false, "", false, fmt.Errorf("adding %q namespace %q for run: %w", namespaceOption.Name, namespaceOption.Path, err)
} }
} }
// If we've got mappings, we're going to have to create a user namespace. // If we've got mappings, we're going to have to create a user namespace.
if len(idmapOptions.UIDMap) > 0 || len(idmapOptions.GIDMap) > 0 || configureUserns { if len(idmapOptions.UIDMap) > 0 || len(idmapOptions.GIDMap) > 0 || configureUserns {
if err := g.AddOrReplaceLinuxNamespace(string(specs.UserNamespace), ""); err != nil { if err := g.AddOrReplaceLinuxNamespace(string(specs.UserNamespace), ""); err != nil {
return false, nil, false, fmt.Errorf("adding new %q namespace for run: %w", string(specs.UserNamespace), err) return false, "", false, fmt.Errorf("adding new %q namespace for run: %w", string(specs.UserNamespace), err)
} }
hostUidmap, hostGidmap, err := unshare.GetHostIDMappings("") hostUidmap, hostGidmap, err := unshare.GetHostIDMappings("")
if err != nil { if err != nil {
return false, nil, false, err return false, "", false, err
} }
for _, m := range idmapOptions.UIDMap { for _, m := range idmapOptions.UIDMap {
g.AddLinuxUIDMapping(m.HostID, m.ContainerID, m.Size) g.AddLinuxUIDMapping(m.HostID, m.ContainerID, m.Size)
@ -712,23 +750,23 @@ func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOpti
} }
if !specifiedNetwork { if !specifiedNetwork {
if err := g.AddOrReplaceLinuxNamespace(string(specs.NetworkNamespace), ""); err != nil { if err := g.AddOrReplaceLinuxNamespace(string(specs.NetworkNamespace), ""); err != nil {
return false, nil, false, fmt.Errorf("adding new %q namespace for run: %w", string(specs.NetworkNamespace), err) return false, "", false, fmt.Errorf("adding new %q namespace for run: %w", string(specs.NetworkNamespace), err)
} }
configureNetwork = (policy != define.NetworkDisabled) configureNetwork = (policy != define.NetworkDisabled)
} }
} else { } else {
if err := g.RemoveLinuxNamespace(string(specs.UserNamespace)); err != nil { if err := g.RemoveLinuxNamespace(string(specs.UserNamespace)); err != nil {
return false, nil, false, fmt.Errorf("removing %q namespace for run: %w", string(specs.UserNamespace), err) return false, "", false, fmt.Errorf("removing %q namespace for run: %w", string(specs.UserNamespace), err)
} }
if !specifiedNetwork { if !specifiedNetwork {
if err := g.RemoveLinuxNamespace(string(specs.NetworkNamespace)); err != nil { if err := g.RemoveLinuxNamespace(string(specs.NetworkNamespace)); err != nil {
return false, nil, false, fmt.Errorf("removing %q namespace for run: %w", string(specs.NetworkNamespace), err) return false, "", false, fmt.Errorf("removing %q namespace for run: %w", string(specs.NetworkNamespace), err)
} }
} }
} }
if configureNetwork { if configureNetwork {
if err := addSysctl([]string{"net"}); err != nil { if err := addSysctl([]string{"net"}); err != nil {
return false, nil, false, err return false, "", false, err
} }
for name, val := range define.DefaultNetworkSysctl { for name, val := range define.DefaultNetworkSysctl {
// Check that the sysctl we are adding is actually supported // Check that the sysctl we are adding is actually supported
@ -736,7 +774,7 @@ func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOpti
p := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1)) p := filepath.Join("/proc/sys", strings.Replace(name, ".", "/", -1))
_, err := os.Stat(p) _, err := os.Stat(p)
if err != nil && !errors.Is(err, os.ErrNotExist) { if err != nil && !errors.Is(err, os.ErrNotExist) {
return false, nil, false, err return false, "", false, err
} }
if err == nil { if err == nil {
g.AddLinuxSysctl(name, val) g.AddLinuxSysctl(name, val)
@ -745,13 +783,13 @@ func setupNamespaces(logger *logrus.Logger, g *generate.Generator, namespaceOpti
} }
} }
} }
return configureNetwork, configureNetworks, configureUTS, nil return configureNetwork, networkString, configureUTS, nil
} }
func (b *Builder) configureNamespaces(g *generate.Generator, options *RunOptions) (bool, []string, error) { func (b *Builder) configureNamespaces(g *generate.Generator, options *RunOptions) (bool, string, error) {
defaultNamespaceOptions, err := DefaultNamespaceOptions() defaultNamespaceOptions, err := DefaultNamespaceOptions()
if err != nil { if err != nil {
return false, nil, err return false, "", err
} }
namespaceOptions := defaultNamespaceOptions namespaceOptions := defaultNamespaceOptions
@ -774,9 +812,9 @@ func (b *Builder) configureNamespaces(g *generate.Generator, options *RunOptions
if networkPolicy == NetworkDisabled { if networkPolicy == NetworkDisabled {
namespaceOptions.AddOrReplace(define.NamespaceOptions{{Name: string(specs.NetworkNamespace), Host: false}}...) namespaceOptions.AddOrReplace(define.NamespaceOptions{{Name: string(specs.NetworkNamespace), Host: false}}...)
} }
configureNetwork, configureNetworks, configureUTS, err := setupNamespaces(options.Logger, g, namespaceOptions, b.IDMappingOptions, networkPolicy) configureNetwork, networkString, configureUTS, err := setupNamespaces(options.Logger, g, namespaceOptions, b.IDMappingOptions, networkPolicy)
if err != nil { if err != nil {
return false, nil, err return false, "", err
} }
if configureUTS { if configureUTS {
@ -803,7 +841,7 @@ func (b *Builder) configureNamespaces(g *generate.Generator, options *RunOptions
spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("HOSTNAME=%s", spec.Hostname)) spec.Process.Env = append(spec.Process.Env, fmt.Sprintf("HOSTNAME=%s", spec.Hostname))
} }
return configureNetwork, configureNetworks, nil return configureNetwork, networkString, nil
} }
func runSetupBoundFiles(bundlePath string, bindFiles map[string]string) (mounts []specs.Mount) { func runSetupBoundFiles(bundlePath string, bindFiles map[string]string) (mounts []specs.Mount) {
@ -1228,11 +1266,3 @@ func (b *Builder) getCacheMount(tokens []string, stageMountPoints map[string]int
succeeded = true succeeded = true
return &volumes[0], targetLock, nil return &volumes[0], targetLock, nil
} }
// setPdeathsig sets a parent-death signal for the process
func setPdeathsig(cmd *exec.Cmd) {
if cmd.SysProcAttr == nil {
cmd.SysProcAttr = &syscall.SysProcAttr{}
}
cmd.SysProcAttr.Pdeathsig = syscall.SIGKILL
}

View File

@ -79,6 +79,8 @@ type Secret struct {
Metadata map[string]string `json:"metadata,omitempty"` Metadata map[string]string `json:"metadata,omitempty"`
// CreatedAt is when the secret was created // CreatedAt is when the secret was created
CreatedAt time.Time `json:"createdAt"` CreatedAt time.Time `json:"createdAt"`
// UpdatedAt is when the secret was updated
UpdatedAt time.Time `json:"updatedAt"`
// Driver is the driver used to store secret data // Driver is the driver used to store secret data
Driver string `json:"driver"` Driver string `json:"driver"`
// DriverOptions are extra options used to run this driver // DriverOptions are extra options used to run this driver
@ -112,6 +114,8 @@ type StoreOptions struct {
Metadata map[string]string Metadata map[string]string
// Labels are labels on the secret // Labels are labels on the secret
Labels map[string]string Labels map[string]string
// Replace existing secret
Replace bool
} }
// NewManager creates a new secrets manager // NewManager creates a new secrets manager
@ -140,6 +144,28 @@ func NewManager(rootPath string) (*SecretsManager, error) {
return manager, nil return manager, nil
} }
func (s *SecretsManager) newSecret(name string) (*Secret, error) {
secr := new(Secret)
secr.Name = name
secr.CreatedAt = time.Now()
secr.UpdatedAt = secr.CreatedAt
for {
newID := stringid.GenerateNonCryptoID()
// GenerateNonCryptoID() gives 64 characters, so we truncate to correct length
newID = newID[0:secretIDLength]
_, err := s.lookupSecret(newID)
if err != nil {
if errors.Is(err, ErrNoSuchSecret) {
secr.ID = newID
break
}
return nil, err
}
}
return secr, nil
}
// Store takes a name, creates a secret and stores the secret metadata and the secret payload. // Store takes a name, creates a secret and stores the secret metadata and the secret payload.
// It returns a generated ID that is associated with the secret. // It returns a generated ID that is associated with the secret.
// The max size for secret data is 512kB. // The max size for secret data is 512kB.
@ -152,7 +178,7 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, opti
if !(len(data) > 0 && len(data) < maxSecretSize) { if !(len(data) > 0 && len(data) < maxSecretSize) {
return "", errDataSize return "", errDataSize
} }
var secr *Secret
s.lockfile.Lock() s.lockfile.Lock()
defer s.lockfile.Unlock() defer s.lockfile.Unlock()
@ -160,23 +186,22 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, opti
if err != nil { if err != nil {
return "", err return "", err
} }
if exist { if exist {
return "", fmt.Errorf("%s: %w", name, errSecretNameInUse) if !options.Replace {
} return "", fmt.Errorf("%s: %w", name, errSecretNameInUse)
}
secr := new(Secret) secr, err = s.lookupSecret(name)
secr.Name = name if err != nil {
return "", err
for { }
newID := stringid.GenerateNonCryptoID() secr.UpdatedAt = time.Now()
// GenerateNonCryptoID() gives 64 characters, so we truncate to correct length } else {
newID = newID[0:secretIDLength] if options.Replace {
_, err := s.lookupSecret(newID) return "", fmt.Errorf("%s: %w", name, ErrNoSuchSecret)
}
secr, err = s.newSecret(name)
if err != nil { if err != nil {
if errors.Is(err, ErrNoSuchSecret) {
secr.ID = newID
break
}
return "", err return "", err
} }
} }
@ -193,7 +218,6 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, opti
secr.Driver = driverType secr.Driver = driverType
secr.Metadata = options.Metadata secr.Metadata = options.Metadata
secr.CreatedAt = time.Now()
secr.DriverOptions = options.DriverOpts secr.DriverOptions = options.DriverOpts
secr.Labels = options.Labels secr.Labels = options.Labels
@ -201,6 +225,13 @@ func (s *SecretsManager) Store(name string, data []byte, driverType string, opti
if err != nil { if err != nil {
return "", err return "", err
} }
if options.Replace {
err = driver.Delete(secr.ID)
if err != nil {
return "", fmt.Errorf("replacing secret %s: %w", name, err)
}
}
err = driver.Store(secr.ID, data) err = driver.Store(secr.ID, data)
if err != nil { if err != nil {
return "", fmt.Errorf("creating secret %s: %w", name, err) return "", fmt.Errorf("creating secret %s: %w", name, err)

View File

@ -1 +1 @@
1.47.0-dev 1.47.0

6
vendor/modules.txt vendored
View File

@ -105,7 +105,7 @@ github.com/containernetworking/cni/pkg/version
# github.com/containernetworking/plugins v1.3.0 # github.com/containernetworking/plugins v1.3.0
## explicit; go 1.20 ## explicit; go 1.20
github.com/containernetworking/plugins/pkg/ns github.com/containernetworking/plugins/pkg/ns
# github.com/containers/buildah v1.30.1-0.20230504052500-e925b5852e07 # github.com/containers/buildah v1.30.1-0.20230627110136-33b7088fec7b
## explicit; go 1.18 ## explicit; go 1.18
github.com/containers/buildah github.com/containers/buildah
github.com/containers/buildah/bind github.com/containers/buildah/bind
@ -128,7 +128,7 @@ github.com/containers/buildah/pkg/rusage
github.com/containers/buildah/pkg/sshagent github.com/containers/buildah/pkg/sshagent
github.com/containers/buildah/pkg/util github.com/containers/buildah/pkg/util
github.com/containers/buildah/util github.com/containers/buildah/util
# github.com/containers/common v0.53.1-0.20230626115555-370c89881624 # github.com/containers/common v0.53.1-0.20230627061926-e6f314e59b81
## explicit; go 1.18 ## explicit; go 1.18
github.com/containers/common/libimage github.com/containers/common/libimage
github.com/containers/common/libimage/define github.com/containers/common/libimage/define
@ -293,7 +293,7 @@ github.com/containers/psgo/internal/dev
github.com/containers/psgo/internal/host github.com/containers/psgo/internal/host
github.com/containers/psgo/internal/proc github.com/containers/psgo/internal/proc
github.com/containers/psgo/internal/process github.com/containers/psgo/internal/process
# github.com/containers/storage v1.46.2-0.20230621123301-73f29956326d # github.com/containers/storage v1.47.0
## explicit; go 1.19 ## explicit; go 1.19
github.com/containers/storage github.com/containers/storage
github.com/containers/storage/drivers github.com/containers/storage/drivers