summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin Rothberg <rothberg@redhat.com>2021-10-13 16:33:38 +0200
committerValentin Rothberg <rothberg@redhat.com>2021-10-26 13:51:45 +0200
commit75f478c08b82a9d6a99628bee5698a85610f863c (patch)
tree2045a9f38472aa878e9d34bfff82afe800845329
parent9d2b8d2791c23b83b6155b046099a83483860c56 (diff)
downloadpodman-75f478c08b82a9d6a99628bee5698a85610f863c.tar.gz
podman-75f478c08b82a9d6a99628bee5698a85610f863c.tar.bz2
podman-75f478c08b82a9d6a99628bee5698a85610f863c.zip
pod create: remove need for pause image
So far, the infra containers of pods required pulling down an image rendering pods not usable in disconnected environments. Instead, build an image locally which uses local pause binary. Fixes: #10354 Signed-off-by: Valentin Rothberg <rothberg@redhat.com>
-rw-r--r--cmd/podman/containers/create.go9
-rw-r--r--cmd/podman/pods/create.go10
-rw-r--r--cmd/podman/system/version.go2
-rw-r--r--docs/source/markdown/podman-pod-create.1.md2
-rw-r--r--libpod/kube.go15
-rw-r--r--pkg/api/handlers/libpod/pods.go17
-rw-r--r--pkg/specgen/generate/pod_create.go97
-rw-r--r--test/e2e/play_kube_test.go19
-rw-r--r--test/system/200-pod.bats30
9 files changed, 135 insertions, 66 deletions
diff --git a/cmd/podman/containers/create.go b/cmd/podman/containers/create.go
index bfeeb7ebe..3be426ae2 100644
--- a/cmd/podman/containers/create.go
+++ b/cmd/podman/containers/create.go
@@ -372,15 +372,10 @@ func createPodIfNecessary(s *specgen.SpecGenerator, netOpts *entities.NetOptions
}
infraOpts := entities.ContainerCreateOptions{ImageVolume: "bind", Net: netOpts, Quiet: true}
- rawImageName := config.DefaultInfraImage
- name, err := PullImage(rawImageName, infraOpts)
- if err != nil {
- fmt.Println(err)
- }
- imageName := name
+ imageName := config.DefaultInfraImage
podGen.InfraImage = imageName
podGen.InfraContainerSpec = specgen.NewSpecGenerator(imageName, false)
- podGen.InfraContainerSpec.RawImageName = rawImageName
+ podGen.InfraContainerSpec.RawImageName = imageName
podGen.InfraContainerSpec.NetworkOptions = podGen.NetworkOptions
err = specgenutil.FillOutSpecGen(podGen.InfraContainerSpec, &infraOpts, []string{})
if err != nil {
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go
index 7c2c72171..0a0d43b53 100644
--- a/cmd/podman/pods/create.go
+++ b/cmd/podman/pods/create.go
@@ -242,16 +242,6 @@ func create(cmd *cobra.Command, args []string) error {
}
if createOptions.Infra {
rawImageName = img
- if !infraOptions.RootFS {
- curr := infraOptions.Quiet
- infraOptions.Quiet = true
- name, err := containers.PullImage(imageName, infraOptions)
- if err != nil {
- fmt.Println(err)
- }
- imageName = name
- infraOptions.Quiet = curr
- }
podSpec.InfraImage = imageName
if infraOptions.Entrypoint != nil {
createOptions.InfraCommand = infraOptions.Entrypoint
diff --git a/cmd/podman/system/version.go b/cmd/podman/system/version.go
index 4502b156c..3ddd19bae 100644
--- a/cmd/podman/system/version.go
+++ b/cmd/podman/system/version.go
@@ -67,7 +67,7 @@ func version(cmd *cobra.Command, args []string) error {
}
if err := tmpl.Execute(w, versions); err != nil {
// On Failure, assume user is using older version of podman version --format and check client
- row = strings.Replace(row, ".Server.", ".", 1)
+ row = strings.ReplaceAll(row, ".Server.", ".")
tmpl, err := report.NewTemplate("version 1.0.0").Parse(row)
if err != nil {
return err
diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md
index 08ac19b8b..061727559 100644
--- a/docs/source/markdown/podman-pod-create.1.md
+++ b/docs/source/markdown/podman-pod-create.1.md
@@ -112,7 +112,7 @@ The command that will be run to start the infra container. Default: "/pause".
#### **--infra-image**=*image*
-The image that will be created for the infra container. Default: "k8s.gcr.io/pause:3.1".
+The custom image that will be used for the infra container. Unless specified, Podman builds a custom local image which does not require pulling down an image.
#### **--infra-name**=*name*
diff --git a/libpod/kube.go b/libpod/kube.go
index 02ac8ed98..ad5acea78 100644
--- a/libpod/kube.go
+++ b/libpod/kube.go
@@ -11,6 +11,7 @@ import (
"strings"
"time"
+ "github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/libpod/network/types"
"github.com/containers/podman/v3/pkg/env"
@@ -468,11 +469,23 @@ func containerToV1Container(ctx context.Context, c *Container) (v1.Container, []
kubeContainer.Name = removeUnderscores(c.Name())
_, image := c.Image()
+
+ // The infra container may have been created with an overlay root FS
+ // instead of an infra image. If so, set the imageto the default K8s
+ // pause one and make sure it's in the storage by pulling it down if
+ // missing.
+ if image == "" && c.IsInfra() {
+ image = config.DefaultInfraImage
+ if _, err := c.runtime.libimageRuntime.Pull(ctx, image, config.PullPolicyMissing, nil); err != nil {
+ return kubeContainer, nil, nil, nil, err
+ }
+ }
+
kubeContainer.Image = image
kubeContainer.Stdin = c.Stdin()
img, _, err := c.runtime.libimageRuntime.LookupImage(image, nil)
if err != nil {
- return kubeContainer, kubeVolumes, nil, annotations, err
+ return kubeContainer, kubeVolumes, nil, annotations, fmt.Errorf("looking up image %q of container %q: %w", image, c.ID(), err)
}
imgData, err := img.Inspect(ctx, nil)
if err != nil {
diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go
index 77d026550..1e64de0ee 100644
--- a/pkg/api/handlers/libpod/pods.go
+++ b/pkg/api/handlers/libpod/pods.go
@@ -1,15 +1,12 @@
package libpod
import (
- "context"
"encoding/json"
"fmt"
"net/http"
"strings"
- "github.com/containers/common/libimage"
"github.com/containers/common/pkg/config"
- "github.com/containers/image/v5/transports/alltransports"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/api/handlers"
@@ -67,20 +64,6 @@ func PodCreate(w http.ResponseWriter, r *http.Request) {
imageName = config.DefaultInfraImage
rawImageName = config.DefaultInfraImage
}
- curr := infraOptions.Quiet
- infraOptions.Quiet = true
- pullOptions := &libimage.PullOptions{}
- pulledImages, err := runtime.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, pullOptions)
- if err != nil {
- utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "could not pull image"))
- return
- }
- if _, err := alltransports.ParseImageName(imageName); err == nil {
- if len(pulledImages) != 0 {
- imageName = pulledImages[0].ID()
- }
- }
- infraOptions.Quiet = curr
psg.InfraImage = imageName
psg.InfraContainerSpec.Image = imageName
psg.InfraContainerSpec.RawImageName = rawImageName
diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go
index a4027eae7..88ebc7ae3 100644
--- a/pkg/specgen/generate/pod_create.go
+++ b/pkg/specgen/generate/pod_create.go
@@ -2,8 +2,12 @@ package generate
import (
"context"
+ "fmt"
+ "io/ioutil"
"net"
+ "os"
+ buildahDefine "github.com/containers/buildah/define"
"github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/libpod"
"github.com/containers/podman/v3/libpod/define"
@@ -14,10 +18,102 @@ import (
"github.com/sirupsen/logrus"
)
+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
+ }
+
+ // NOTE: Having the pause binary in its own directory keeps the door
+ // open for replacing the image building with using an overlay root FS.
+ // The latter turned out to be complex and error prone (see #11956) but
+ // we may be able to come up with a proper solution at a later point in
+ // time.
+ pausePath, err := rtConfig.FindHelperBinary("pause/pause", false)
+ if err != nil {
+ return "", fmt.Errorf("finding pause binary: %w", err)
+ }
+
+ buildContent := fmt.Sprintf(`FROM scratch
+COPY %s /pause
+ENTRYPOINT ["/pause"]`, pausePath)
+
+ tmpF, err := ioutil.TempFile("", "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,
+ IIDFile: "/dev/null", // prevents Buildah from writing the ID on stdout
+ }
+ if _, _, err := rt.Build(context.Background(), buildOptions, tmpF.Name()); err != nil {
+ return "", err
+ }
+
+ return imageName, nil
+}
+
+func pullOrBuildInfraImage(p *entities.PodSpec, rt *libpod.Runtime) error {
+ if p.PodSpecGen.NoInfra {
+ return nil
+ }
+
+ rtConfig, err := rt.GetConfigNoCopy()
+ if err != nil {
+ return err
+ }
+
+ // NOTE: we need pull down the infra image if it was explicitly set by
+ // the user (or containers.conf) to the non-default one.
+ imageName := p.PodSpecGen.InfraImage
+ if imageName == "" {
+ imageName = rtConfig.Engine.InfraImage
+ }
+
+ if imageName != config.DefaultInfraImage {
+ _, err := rt.LibimageRuntime().Pull(context.Background(), imageName, config.PullPolicyMissing, nil)
+ if err != nil {
+ return err
+ }
+ } else {
+ name, err := buildPauseImage(rt, rtConfig)
+ if err != nil {
+ return fmt.Errorf("building local pause image: %w", err)
+ }
+ imageName = name
+ }
+
+ p.PodSpecGen.InfraImage = imageName
+ p.PodSpecGen.InfraContainerSpec.RawImageName = imageName
+
+ return nil
+}
+
func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) {
if err := p.PodSpecGen.Validate(); err != nil {
return nil, err
}
+
+ if err := pullOrBuildInfraImage(p, rt); err != nil {
+ return nil, err
+ }
+
if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
var err error
p.PodSpecGen.InfraContainerSpec, err = MapSpec(&p.PodSpecGen)
@@ -35,7 +131,6 @@ func MakePod(p *entities.PodSpec, rt *libpod.Runtime) (*libpod.Pod, error) {
return nil, err
}
if !p.PodSpecGen.NoInfra && p.PodSpecGen.InfraContainerSpec != nil {
- p.PodSpecGen.InfraContainerSpec.ContainerCreateCommand = []string{} // we do NOT want os.Args as the command, will display the pod create cmd
if p.PodSpecGen.InfraContainerSpec.Name == "" {
p.PodSpecGen.InfraContainerSpec.Name = pod.ID()[:12] + "-infra"
}
diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go
index d5b913743..b0b927445 100644
--- a/test/e2e/play_kube_test.go
+++ b/test/e2e/play_kube_test.go
@@ -11,7 +11,6 @@ import (
"text/template"
"time"
- "github.com/containers/common/pkg/config"
"github.com/containers/podman/v3/libpod/define"
"github.com/containers/podman/v3/pkg/util"
. "github.com/containers/podman/v3/test/utils"
@@ -1120,24 +1119,6 @@ var _ = Describe("Podman play kube", func() {
Expect(label).To(ContainSubstring("unconfined_u:system_r:spc_t:s0"))
})
- It("podman play kube should use default infra_image", func() {
- err := writeYaml(checkInfraImagePodYaml, kubeYaml)
- Expect(err).To(BeNil())
-
- kube := podmanTest.Podman([]string{"play", "kube", kubeYaml})
- kube.WaitWithDefaultTimeout()
- Expect(kube).Should(Exit(0))
-
- podInspect := podmanTest.Podman([]string{"inspect", "check-infra-image", "--format", "{{ .InfraContainerID }}"})
- podInspect.WaitWithDefaultTimeout()
- infraContainerID := podInspect.OutputToString()
-
- conInspect := podmanTest.Podman([]string{"inspect", infraContainerID, "--format", "{{ .ImageName }}"})
- conInspect.WaitWithDefaultTimeout()
- infraContainerImage := conInspect.OutputToString()
- Expect(infraContainerImage).To(Equal(config.DefaultInfraImage))
- })
-
It("podman play kube --no-host", func() {
err := writeYaml(checkInfraImagePodYaml, kubeYaml)
Expect(err).To(BeNil())
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index 86f3610ab..09a419914 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -60,6 +60,10 @@ function teardown() {
run_podman pod rm -f -t 0 $podid
}
+function rm_podman_pause_image() {
+ run_podman version --format "{{.Server.Version}}-{{.Server.Built}}"
+ run_podman rmi -f "localhost/podman-pause:$output"
+}
@test "podman pod - communicating between pods" {
podname=pod$(random_string)
@@ -100,19 +104,14 @@ function teardown() {
# Clean up. First the nc -l container...
run_podman rm $cid1
- # ...then, from pause container, find the image ID of the pause image...
- run_podman pod inspect --format '{{(index .Containers 0).ID}}' $podname
- pause_cid="$output"
- run_podman container inspect --format '{{.Image}}' $pause_cid
- pause_iid="$output"
-
# ...then rm the pod, then rmi the pause image so we don't leave strays.
run_podman pod rm $podname
- run_podman rmi $pause_iid
# Pod no longer exists
run_podman 1 pod exists $podid
run_podman 1 pod exists $podname
+
+ rm_podman_pause_image
}
@test "podman pod - communicating via /dev/shm " {
@@ -133,6 +132,10 @@ function teardown() {
# Pod no longer exists
run_podman 1 pod exists $podid
run_podman 1 pod exists $podname
+
+ # Pause image hasn't been pulled
+ run_podman 1 image exists k8s.gcr.io/pause:3.5
+ rm_podman_pause_image
}
# Random byte
@@ -303,16 +306,25 @@ EOF
run_podman rm $cid
run_podman pod rm -t 0 -f mypod
run_podman rmi $infra_image
-
}
@test "podman pod create should fail when infra-name is already in use" {
local infra_name="infra_container_$(random_string 10 | tr A-Z a-z)"
- run_podman pod create --infra-name "$infra_name"
+ local pod_name="$(random_string 10 | tr A-Z a-z)"
+
+ # Note that the internal pause image is built even when --infra-image is
+ # set to the K8s one.
+ run_podman pod create --name $pod_name --infra-name "$infra_name" --infra-image "k8s.gcr.io/pause:3.5"
run_podman '?' pod create --infra-name "$infra_name"
if [ $status -eq 0 ]; then
die "Podman should fail when user try to create two pods with the same infra-name value"
fi
+ run_podman pod rm -f $pod_name
+ run_podman images -a
+
+ # Pause image hasn't been pulled
+ run_podman 1 image exists k8s.gcr.io/pause:3.5
+ rm_podman_pause_image
}
# vim: filetype=sh