summaryrefslogtreecommitdiff
path: root/pkg/specgen/generate/pause_image.go
blob: 1b502927fb9d4f793715faa59be467e9fe5b773a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
package generate

import (
	"context"
	"fmt"
	"os"

	buildahDefine "github.com/containers/buildah/define"
	"github.com/containers/common/pkg/config"
	"github.com/containers/podman/v4/libpod"
	"github.com/containers/podman/v4/libpod/define"
)

// PullOrBuildInfraImage pulls down the specified image or the one set in
// containers.conf.  If none is set, it builds a local pause image.
func PullOrBuildInfraImage(rt *libpod.Runtime, imageName string) (string, error) {
	rtConfig, err := rt.GetConfigNoCopy()
	if err != nil {
		return "", err
	}

	if imageName == "" {
		imageName = rtConfig.Engine.InfraImage
	}

	if imageName != "" {
		_, err := rt.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, nil)
		if err != nil {
			return "", err
		}
		return imageName, nil
	}

	name, err := buildPauseImage(rt, rtConfig)
	if err != nil {
		return "", fmt.Errorf("building local pause image: %w", err)
	}
	return name, nil
}

func buildPauseImage(rt *libpod.Runtime, rtConfig *config.Config) (string, error) {
	version, err := define.GetVersion()
	if err != nil {
		return "", err
	}
	imageName := fmt.Sprintf("localhost/podman-pause:%s-%d", version.Version, version.Built)

	// First check if the image has already been built.
	if _, _, err := rt.LibimageRuntime().LookupImage(imageName, nil); err == nil {
		return imageName, nil
	}

	// Also look into the path as some distributions install catatonit in
	// /usr/bin.
	catatonitPath, err := rtConfig.FindHelperBinary("catatonit", true)
	if err != nil {
		return "", fmt.Errorf("finding pause binary: %w", err)
	}

	buildContent := fmt.Sprintf(`FROM scratch
COPY %s /catatonit
ENTRYPOINT ["/catatonit", "-P"]`, catatonitPath)

	tmpF, err := os.CreateTemp("", "pause.containerfile")
	if err != nil {
		return "", err
	}
	if _, err := tmpF.WriteString(buildContent); err != nil {
		return "", err
	}
	if err := tmpF.Close(); err != nil {
		return "", err
	}
	defer os.Remove(tmpF.Name())

	buildOptions := buildahDefine.BuildOptions{
		CommonBuildOpts: &buildahDefine.CommonBuildOptions{},
		Output:          imageName,
		Quiet:           true,
		IgnoreFile:      "/dev/null", // makes sure to not read a local .ignorefile (see #13529)
		IIDFile:         "/dev/null", // prevents Buildah from writing the ID on stdout
		IDMappingOptions: &buildahDefine.IDMappingOptions{
			// Use the host UID/GID mappings for the build to avoid issues when
			// running with a custom mapping (BZ #2083997).
			HostUIDMapping: true,
			HostGIDMapping: true,
		},
	}
	if _, _, err := rt.Build(context.Background(), buildOptions, tmpF.Name()); err != nil {
		return "", err
	}

	return imageName, nil
}