From d28e85741fedb89be48a03d4f05687e970eb71b9 Mon Sep 17 00:00:00 2001 From: cdoern Date: Wed, 14 Jul 2021 16:30:28 -0400 Subject: InfraContainer Rework InfraContainer should go through the same creation process as regular containers. This change was from the cmd level down, involving new container CLI opts and specgen creating functions. What now happens is that both container and pod cli options are populated in cmd and used to create a podSpecgen and a containerSpecgen. The process then goes as follows FillOutSpecGen (infra) -> MapSpec (podOpts -> infraOpts) -> PodCreate -> MakePod -> createPodOptions -> NewPod -> CompleteSpec (infra) -> MakeContainer -> NewContainer -> newContainer -> AddInfra (to pod state) Signed-off-by: cdoern --- pkg/api/handlers/libpod/pods.go | 65 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 58 insertions(+), 7 deletions(-) (limited to 'pkg/api/handlers/libpod/pods.go') diff --git a/pkg/api/handlers/libpod/pods.go b/pkg/api/handlers/libpod/pods.go index ff105bc48..3d6cf093b 100644 --- a/pkg/api/handlers/libpod/pods.go +++ b/pkg/api/handlers/libpod/pods.go @@ -1,11 +1,15 @@ 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" @@ -14,6 +18,7 @@ import ( "github.com/containers/podman/v3/pkg/domain/infra/abi" "github.com/containers/podman/v3/pkg/specgen" "github.com/containers/podman/v3/pkg/specgen/generate" + "github.com/containers/podman/v3/pkg/specgenutil" "github.com/containers/podman/v3/pkg/util" "github.com/gorilla/schema" "github.com/pkg/errors" @@ -25,24 +30,70 @@ func PodCreate(w http.ResponseWriter, r *http.Request) { runtime = r.Context().Value("runtime").(*libpod.Runtime) err error ) - var psg specgen.PodSpecGenerator + psg := specgen.PodSpecGenerator{InfraContainerSpec: &specgen.SpecGenerator{}} if err := json.NewDecoder(r.Body).Decode(&psg); err != nil { - utils.Error(w, "failed to decode specgen", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen")) + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen")) return } - // parse userns so we get the valid default value of userns - psg.Userns, err = specgen.ParseUserNamespace(psg.Userns.String()) if err != nil { - utils.Error(w, "failed to parse userns", http.StatusInternalServerError, errors.Wrap(err, "failed to parse userns")) + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen")) return } - pod, err := generate.MakePod(&psg, runtime) + if !psg.NoInfra { + infraOptions := &entities.ContainerCreateOptions{ImageVolume: "bind", IsInfra: true, Net: &entities.NetOptions{}} // options for pulling the image and FillOutSpec + err = specgenutil.FillOutSpecGen(psg.InfraContainerSpec, infraOptions, []string{}) // necessary for default values in many cases (userns, idmappings) + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "error filling out specgen")) + return + } + out, err := json.Marshal(psg) // marshal our spec so the matching options can be unmarshaled into infra + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen")) + return + } + tempSpec := &specgen.SpecGenerator{} // temporary spec since infra cannot be decoded into + err = json.Unmarshal(out, tempSpec) // unmarhal matching options + if err != nil { + utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "failed to decode specgen")) + return + } + psg.InfraContainerSpec = tempSpec // set infra spec equal to temp + // a few extra that do not have the same json tags + psg.InfraContainerSpec.Name = psg.InfraName + psg.InfraContainerSpec.ConmonPidFile = psg.InfraConmonPidFile + psg.InfraContainerSpec.ContainerCreateCommand = psg.InfraCommand + imageName := psg.InfraImage + rawImageName := psg.InfraImage + if imageName == "" { + 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 + } + podSpecComplete := entities.PodSpec{PodSpecGen: psg} + pod, err := generate.MakePod(&podSpecComplete, runtime) if err != nil { httpCode := http.StatusInternalServerError if errors.Cause(err) == define.ErrPodExists { httpCode = http.StatusConflict } - utils.Error(w, "Something went wrong.", httpCode, err) + utils.Error(w, "Something went wrong.", httpCode, errors.Wrap(err, "failed to make pod")) return } utils.WriteResponse(w, http.StatusCreated, handlers.IDResponse{ID: pod.ID()}) -- cgit v1.2.3-54-g00ecf