mirror of
				https://github.com/containers/podman.git
				synced 2025-11-04 08:56:05 +08:00 
			
		
		
		
	when using the compatibility mode as rootless, containers that were created were not setting their host names correctly due to the netmode not being set. Fixes: #7934 Signed-off-by: baude <bbaude@redhat.com>
		
			
				
	
	
		
			276 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			276 lines
		
	
	
		
			8.4 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package compat
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"encoding/json"
 | 
						|
	"fmt"
 | 
						|
	"net/http"
 | 
						|
	"strings"
 | 
						|
 | 
						|
	"github.com/containers/common/pkg/config"
 | 
						|
	"github.com/containers/podman/v2/libpod"
 | 
						|
	"github.com/containers/podman/v2/libpod/define"
 | 
						|
	image2 "github.com/containers/podman/v2/libpod/image"
 | 
						|
	"github.com/containers/podman/v2/pkg/api/handlers"
 | 
						|
	"github.com/containers/podman/v2/pkg/api/handlers/utils"
 | 
						|
	"github.com/containers/podman/v2/pkg/namespaces"
 | 
						|
	"github.com/containers/podman/v2/pkg/rootless"
 | 
						|
	"github.com/containers/podman/v2/pkg/signal"
 | 
						|
	createconfig "github.com/containers/podman/v2/pkg/spec"
 | 
						|
	"github.com/containers/podman/v2/pkg/specgen"
 | 
						|
	"github.com/containers/storage"
 | 
						|
	"github.com/gorilla/schema"
 | 
						|
	"github.com/pkg/errors"
 | 
						|
	"golang.org/x/sys/unix"
 | 
						|
)
 | 
						|
 | 
						|
func CreateContainer(w http.ResponseWriter, r *http.Request) {
 | 
						|
	runtime := r.Context().Value("runtime").(*libpod.Runtime)
 | 
						|
	decoder := r.Context().Value("decoder").(*schema.Decoder)
 | 
						|
	input := handlers.CreateContainerConfig{}
 | 
						|
	query := struct {
 | 
						|
		Name string `schema:"name"`
 | 
						|
	}{
 | 
						|
		// override any golang type defaults
 | 
						|
	}
 | 
						|
	if err := decoder.Decode(&query, r.URL.Query()); err != nil {
 | 
						|
		utils.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest,
 | 
						|
			errors.Wrapf(err, "failed to parse parameters for %s", r.URL.String()))
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if err := json.NewDecoder(r.Body).Decode(&input); err != nil {
 | 
						|
		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "Decode()"))
 | 
						|
		return
 | 
						|
	}
 | 
						|
	if len(input.HostConfig.Links) > 0 {
 | 
						|
		utils.Error(w, utils.ErrLinkNotSupport.Error(), http.StatusBadRequest, errors.Wrapf(utils.ErrLinkNotSupport, "bad parameter"))
 | 
						|
		return
 | 
						|
	}
 | 
						|
	newImage, err := runtime.ImageRuntime().NewFromLocal(input.Image)
 | 
						|
	if err != nil {
 | 
						|
		if errors.Cause(err) == define.ErrNoSuchImage {
 | 
						|
			utils.Error(w, "No such image", http.StatusNotFound, err)
 | 
						|
			return
 | 
						|
		}
 | 
						|
 | 
						|
		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "NewFromLocal()"))
 | 
						|
		return
 | 
						|
	}
 | 
						|
	containerConfig, err := runtime.GetConfig()
 | 
						|
	if err != nil {
 | 
						|
		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "GetConfig()"))
 | 
						|
		return
 | 
						|
	}
 | 
						|
	cc, err := makeCreateConfig(r.Context(), containerConfig, input, newImage)
 | 
						|
	if err != nil {
 | 
						|
		utils.Error(w, "Something went wrong.", http.StatusInternalServerError, errors.Wrap(err, "makeCreatConfig()"))
 | 
						|
		return
 | 
						|
	}
 | 
						|
	cc.Name = query.Name
 | 
						|
	utils.CreateContainer(r.Context(), w, runtime, &cc)
 | 
						|
}
 | 
						|
 | 
						|
func makeCreateConfig(ctx context.Context, containerConfig *config.Config, input handlers.CreateContainerConfig, newImage *image2.Image) (createconfig.CreateConfig, error) {
 | 
						|
	var (
 | 
						|
		err  error
 | 
						|
		init bool
 | 
						|
	)
 | 
						|
	env := make(map[string]string)
 | 
						|
	stopSignal := unix.SIGTERM
 | 
						|
	if len(input.StopSignal) > 0 {
 | 
						|
		stopSignal, err = signal.ParseSignal(input.StopSignal)
 | 
						|
		if err != nil {
 | 
						|
			return createconfig.CreateConfig{}, err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	workDir, err := newImage.WorkingDir(ctx)
 | 
						|
	if err != nil {
 | 
						|
		return createconfig.CreateConfig{}, err
 | 
						|
	}
 | 
						|
	if workDir == "" {
 | 
						|
		workDir = "/"
 | 
						|
	}
 | 
						|
	if len(input.WorkingDir) > 0 {
 | 
						|
		workDir = input.WorkingDir
 | 
						|
	}
 | 
						|
 | 
						|
	// Only use image's Cmd when the user does not set the entrypoint
 | 
						|
	if input.Entrypoint == nil && len(input.Cmd) == 0 {
 | 
						|
		cmdSlice, err := newImage.Cmd(ctx)
 | 
						|
		if err != nil {
 | 
						|
			return createconfig.CreateConfig{}, err
 | 
						|
		}
 | 
						|
		input.Cmd = cmdSlice
 | 
						|
	}
 | 
						|
 | 
						|
	if input.Entrypoint == nil {
 | 
						|
		entrypointSlice, err := newImage.Entrypoint(ctx)
 | 
						|
		if err != nil {
 | 
						|
			return createconfig.CreateConfig{}, err
 | 
						|
		}
 | 
						|
		input.Entrypoint = entrypointSlice
 | 
						|
	}
 | 
						|
 | 
						|
	stopTimeout := containerConfig.Engine.StopTimeout
 | 
						|
	if input.StopTimeout != nil {
 | 
						|
		stopTimeout = uint(*input.StopTimeout)
 | 
						|
	}
 | 
						|
	c := createconfig.CgroupConfig{
 | 
						|
		Cgroups:      "", // podman
 | 
						|
		Cgroupns:     "", // podman
 | 
						|
		CgroupParent: "", // podman
 | 
						|
		CgroupMode:   "", // podman
 | 
						|
	}
 | 
						|
	security := createconfig.SecurityConfig{
 | 
						|
		CapAdd:             input.HostConfig.CapAdd,
 | 
						|
		CapDrop:            input.HostConfig.CapDrop,
 | 
						|
		LabelOpts:          nil,   // podman
 | 
						|
		NoNewPrivs:         false, // podman
 | 
						|
		ApparmorProfile:    "",    // podman
 | 
						|
		SeccompProfilePath: "",
 | 
						|
		SecurityOpts:       input.HostConfig.SecurityOpt,
 | 
						|
		Privileged:         input.HostConfig.Privileged,
 | 
						|
		ReadOnlyRootfs:     input.HostConfig.ReadonlyRootfs,
 | 
						|
		ReadOnlyTmpfs:      false, // podman-only
 | 
						|
		Sysctl:             input.HostConfig.Sysctls,
 | 
						|
	}
 | 
						|
 | 
						|
	var netmode namespaces.NetworkMode
 | 
						|
	if rootless.IsRootless() {
 | 
						|
		netmode = namespaces.NetworkMode(specgen.Slirp)
 | 
						|
	}
 | 
						|
 | 
						|
	network := createconfig.NetworkConfig{
 | 
						|
		DNSOpt:       input.HostConfig.DNSOptions,
 | 
						|
		DNSSearch:    input.HostConfig.DNSSearch,
 | 
						|
		DNSServers:   input.HostConfig.DNS,
 | 
						|
		ExposedPorts: input.ExposedPorts,
 | 
						|
		HTTPProxy:    false, // podman
 | 
						|
		IP6Address:   "",
 | 
						|
		IPAddress:    "",
 | 
						|
		LinkLocalIP:  nil, // docker-only
 | 
						|
		MacAddress:   input.MacAddress,
 | 
						|
		NetMode:      netmode,
 | 
						|
		Network:      input.HostConfig.NetworkMode.NetworkName(),
 | 
						|
		NetworkAlias: nil, // docker-only now
 | 
						|
		PortBindings: input.HostConfig.PortBindings,
 | 
						|
		Publish:      nil, // podmanseccompPath
 | 
						|
		PublishAll:   input.HostConfig.PublishAllPorts,
 | 
						|
	}
 | 
						|
 | 
						|
	uts := createconfig.UtsConfig{
 | 
						|
		UtsMode:  namespaces.UTSMode(input.HostConfig.UTSMode),
 | 
						|
		NoHosts:  false, //podman
 | 
						|
		HostAdd:  input.HostConfig.ExtraHosts,
 | 
						|
		Hostname: input.Hostname,
 | 
						|
	}
 | 
						|
 | 
						|
	z := createconfig.UserConfig{
 | 
						|
		GroupAdd:   input.HostConfig.GroupAdd,
 | 
						|
		IDMappings: &storage.IDMappingOptions{}, // podman //TODO <--- fix this,
 | 
						|
		UsernsMode: namespaces.UsernsMode(input.HostConfig.UsernsMode),
 | 
						|
		User:       input.User,
 | 
						|
	}
 | 
						|
	pidConfig := createconfig.PidConfig{PidMode: namespaces.PidMode(input.HostConfig.PidMode)}
 | 
						|
	// TODO: We should check that these binds are all listed in the `Volumes`
 | 
						|
	// key since it doesn't make sense to define a `Binds` element for a
 | 
						|
	// container path which isn't defined as a volume
 | 
						|
	volumes := input.HostConfig.Binds
 | 
						|
 | 
						|
	// Docker is more flexible about its input where podman throws
 | 
						|
	// away incorrectly formatted variables so we cannot reuse the
 | 
						|
	// parsing of the env input
 | 
						|
	// [Foo Other=one Blank=]
 | 
						|
	imgEnv, err := newImage.Env(ctx)
 | 
						|
	if err != nil {
 | 
						|
		return createconfig.CreateConfig{}, err
 | 
						|
	}
 | 
						|
	input.Env = append(imgEnv, input.Env...)
 | 
						|
	for _, e := range input.Env {
 | 
						|
		splitEnv := strings.Split(e, "=")
 | 
						|
		switch len(splitEnv) {
 | 
						|
		case 0:
 | 
						|
			continue
 | 
						|
		case 1:
 | 
						|
			env[splitEnv[0]] = ""
 | 
						|
		default:
 | 
						|
			env[splitEnv[0]] = strings.Join(splitEnv[1:], "=")
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	// format the tmpfs mounts into a []string from map
 | 
						|
	tmpfs := make([]string, 0, len(input.HostConfig.Tmpfs))
 | 
						|
	for k, v := range input.HostConfig.Tmpfs {
 | 
						|
		tmpfs = append(tmpfs, fmt.Sprintf("%s:%s", k, v))
 | 
						|
	}
 | 
						|
 | 
						|
	if input.HostConfig.Init != nil && *input.HostConfig.Init {
 | 
						|
		init = true
 | 
						|
	}
 | 
						|
 | 
						|
	m := createconfig.CreateConfig{
 | 
						|
		Annotations:   nil, // podman
 | 
						|
		Args:          nil,
 | 
						|
		Cgroup:        c,
 | 
						|
		CidFile:       "",
 | 
						|
		ConmonPidFile: "", // podman
 | 
						|
		Command:       input.Cmd,
 | 
						|
		UserCommand:   input.Cmd, // podman
 | 
						|
		Detach:        false,     //
 | 
						|
		// Devices:            input.HostConfig.Devices,
 | 
						|
		Entrypoint:        input.Entrypoint,
 | 
						|
		Env:               env,
 | 
						|
		HealthCheck:       nil, //
 | 
						|
		Init:              init,
 | 
						|
		InitPath:          "", // tbd
 | 
						|
		Image:             input.Image,
 | 
						|
		ImageID:           newImage.ID(),
 | 
						|
		BuiltinImgVolumes: nil, // podman
 | 
						|
		ImageVolumeType:   "",  // podman
 | 
						|
		Interactive:       input.OpenStdin,
 | 
						|
		// IpcMode:           input.HostConfig.IpcMode,
 | 
						|
		Labels:    input.Labels,
 | 
						|
		LogDriver: input.HostConfig.LogConfig.Type, // is this correct
 | 
						|
		// LogDriverOpt:       input.HostConfig.LogConfig.Config,
 | 
						|
		Name:          input.Name,
 | 
						|
		Network:       network,
 | 
						|
		Pod:           "",    // podman
 | 
						|
		PodmanPath:    "",    // podman
 | 
						|
		Quiet:         false, // front-end only
 | 
						|
		Resources:     createconfig.CreateResourceConfig{},
 | 
						|
		RestartPolicy: input.HostConfig.RestartPolicy.Name,
 | 
						|
		Rm:            input.HostConfig.AutoRemove,
 | 
						|
		StopSignal:    stopSignal,
 | 
						|
		StopTimeout:   stopTimeout,
 | 
						|
		Systemd:       false, // podman
 | 
						|
		Tmpfs:         tmpfs,
 | 
						|
		User:          z,
 | 
						|
		Uts:           uts,
 | 
						|
		Tty:           input.Tty,
 | 
						|
		Mounts:        nil, // we populate
 | 
						|
		// MountsFlag:         input.HostConfig.Mounts,
 | 
						|
		NamedVolumes: nil, // we populate
 | 
						|
		Volumes:      volumes,
 | 
						|
		VolumesFrom:  input.HostConfig.VolumesFrom,
 | 
						|
		WorkDir:      workDir,
 | 
						|
		Rootfs:       "", // podman
 | 
						|
		Security:     security,
 | 
						|
		Syslog:       false, // podman
 | 
						|
 | 
						|
		Pid: pidConfig,
 | 
						|
	}
 | 
						|
 | 
						|
	fullCmd := append(input.Entrypoint, input.Cmd...)
 | 
						|
	if len(fullCmd) > 0 {
 | 
						|
		m.PodmanPath = fullCmd[0]
 | 
						|
		if len(fullCmd) == 1 {
 | 
						|
			m.Args = fullCmd
 | 
						|
		} else {
 | 
						|
			m.Args = fullCmd[1:]
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return m, nil
 | 
						|
}
 |