mirror of
https://github.com/containers/podman.git
synced 2025-06-25 20:26:51 +08:00
Merge pull request #1907 from baude/createpodautomatically
create pod on the fly
This commit is contained in:
@ -11,6 +11,7 @@ import (
|
|||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
"github.com/containers/libpod/cmd/podman/libpodruntime"
|
||||||
|
"github.com/containers/libpod/cmd/podman/shared"
|
||||||
"github.com/containers/libpod/libpod"
|
"github.com/containers/libpod/libpod"
|
||||||
"github.com/containers/libpod/libpod/image"
|
"github.com/containers/libpod/libpod/image"
|
||||||
ann "github.com/containers/libpod/pkg/annotations"
|
ann "github.com/containers/libpod/pkg/annotations"
|
||||||
@ -375,8 +376,8 @@ func configureEntrypoint(c *cli.Context, data *inspect.ImageData) []string {
|
|||||||
return entrypoint
|
return entrypoint
|
||||||
}
|
}
|
||||||
|
|
||||||
func configurePod(c *cli.Context, runtime *libpod.Runtime, namespaces map[string]string) (map[string]string, error) {
|
func configurePod(c *cli.Context, runtime *libpod.Runtime, namespaces map[string]string, podName string) (map[string]string, error) {
|
||||||
pod, err := runtime.LookupPod(c.String("pod"))
|
pod, err := runtime.LookupPod(podName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return namespaces, err
|
return namespaces, err
|
||||||
}
|
}
|
||||||
@ -409,6 +410,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||||||
inputCommand, command []string
|
inputCommand, command []string
|
||||||
memoryLimit, memoryReservation, memorySwap, memoryKernel int64
|
memoryLimit, memoryReservation, memorySwap, memoryKernel int64
|
||||||
blkioWeight uint16
|
blkioWeight uint16
|
||||||
|
namespaces map[string]string
|
||||||
)
|
)
|
||||||
idmappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidname"), c.String("subgidname"))
|
idmappings, err := util.ParseIDMapping(c.StringSlice("uidmap"), c.StringSlice("gidmap"), c.String("subuidname"), c.String("subgidname"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -492,12 +494,21 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||||||
return nil, errors.Errorf("--cpu-quota and --cpus cannot be set together")
|
return nil, errors.Errorf("--cpu-quota and --cpus cannot be set together")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// EXPOSED PORTS
|
||||||
|
var portBindings map[nat.Port][]nat.PortBinding
|
||||||
|
if data != nil {
|
||||||
|
portBindings, err = cc.ExposedPorts(c.StringSlice("expose"), c.StringSlice("publish"), c.Bool("publish-all"), data.ContainerConfig.ExposedPorts)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Kernel Namespaces
|
// Kernel Namespaces
|
||||||
// TODO Fix handling of namespace from pod
|
// TODO Fix handling of namespace from pod
|
||||||
// Instead of integrating here, should be done in libpod
|
// Instead of integrating here, should be done in libpod
|
||||||
// However, that also involves setting up security opts
|
// However, that also involves setting up security opts
|
||||||
// when the pod's namespace is integrated
|
// when the pod's namespace is integrated
|
||||||
namespaces := map[string]string{
|
namespaces = map[string]string{
|
||||||
"pid": c.String("pid"),
|
"pid": c.String("pid"),
|
||||||
"net": c.String("net"),
|
"net": c.String("net"),
|
||||||
"ipc": c.String("ipc"),
|
"ipc": c.String("ipc"),
|
||||||
@ -505,8 +516,41 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||||||
"uts": c.String("uts"),
|
"uts": c.String("uts"),
|
||||||
}
|
}
|
||||||
|
|
||||||
|
originalPodName := c.String("pod")
|
||||||
|
podName := strings.Replace(originalPodName, "new:", "", 1)
|
||||||
|
// after we strip out :new, make sure there is something left for a pod name
|
||||||
|
if len(podName) < 1 && c.IsSet("pod") {
|
||||||
|
return nil, errors.Errorf("new pod name must be at least one character")
|
||||||
|
}
|
||||||
if c.IsSet("pod") {
|
if c.IsSet("pod") {
|
||||||
namespaces, err = configurePod(c, runtime, namespaces)
|
if strings.HasPrefix(originalPodName, "new:") {
|
||||||
|
// pod does not exist; lets make it
|
||||||
|
var podOptions []libpod.PodCreateOption
|
||||||
|
podOptions = append(podOptions, libpod.WithPodName(podName), libpod.WithInfraContainer(), libpod.WithPodCgroups())
|
||||||
|
if len(portBindings) > 0 {
|
||||||
|
ociPortBindings, err := cc.NatToOCIPortBindings(portBindings)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
podOptions = append(podOptions, libpod.WithInfraContainerPorts(ociPortBindings))
|
||||||
|
}
|
||||||
|
|
||||||
|
podNsOptions, err := shared.GetNamespaceOptions(strings.Split(DefaultKernelNamespaces, ","))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
podOptions = append(podOptions, podNsOptions...)
|
||||||
|
// make pod
|
||||||
|
pod, err := runtime.NewPod(ctx, podOptions...)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
logrus.Debugf("pod %s created by new container request", pod.ID())
|
||||||
|
|
||||||
|
// The container now cannot have port bindings; so we reset the map
|
||||||
|
portBindings = make(map[nat.Port][]nat.PortBinding)
|
||||||
|
}
|
||||||
|
namespaces, err = configurePod(c, runtime, namespaces, podName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -535,7 +579,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||||||
// Make sure if network is set to container namespace, port binding is not also being asked for
|
// Make sure if network is set to container namespace, port binding is not also being asked for
|
||||||
netMode := ns.NetworkMode(namespaces["net"])
|
netMode := ns.NetworkMode(namespaces["net"])
|
||||||
if netMode.IsContainer() {
|
if netMode.IsContainer() {
|
||||||
if len(c.StringSlice("publish")) > 0 || c.Bool("publish-all") {
|
if len(portBindings) > 0 {
|
||||||
return nil, errors.Errorf("cannot set port bindings on an existing container network namespace")
|
return nil, errors.Errorf("cannot set port bindings on an existing container network namespace")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -644,15 +688,6 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||||||
return nil, errors.Errorf("No command specified on command line or as CMD or ENTRYPOINT in this image")
|
return nil, errors.Errorf("No command specified on command line or as CMD or ENTRYPOINT in this image")
|
||||||
}
|
}
|
||||||
|
|
||||||
// EXPOSED PORTS
|
|
||||||
var portBindings map[nat.Port][]nat.PortBinding
|
|
||||||
if data != nil {
|
|
||||||
portBindings, err = cc.ExposedPorts(c.StringSlice("expose"), c.StringSlice("publish"), c.Bool("publish-all"), data.ContainerConfig.ExposedPorts)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// SHM Size
|
// SHM Size
|
||||||
shmSize, err := units.FromHumanSize(c.String("shm-size"))
|
shmSize, err := units.FromHumanSize(c.String("shm-size"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -746,7 +781,7 @@ func parseCreateOpts(ctx context.Context, c *cli.Context, runtime *libpod.Runtim
|
|||||||
NetMode: netMode,
|
NetMode: netMode,
|
||||||
UtsMode: utsMode,
|
UtsMode: utsMode,
|
||||||
PidMode: pidMode,
|
PidMode: pidMode,
|
||||||
Pod: c.String("pod"),
|
Pod: podName,
|
||||||
Privileged: c.Bool("privileged"),
|
Privileged: c.Bool("privileged"),
|
||||||
Publish: c.StringSlice("publish"),
|
Publish: c.StringSlice("publish"),
|
||||||
PublishAll: c.Bool("publish-all"),
|
PublishAll: c.Bool("publish-all"),
|
||||||
|
@ -455,7 +455,8 @@ Tune the container's pids limit. Set `-1` to have unlimited pids for the contain
|
|||||||
|
|
||||||
**--pod**=""
|
**--pod**=""
|
||||||
|
|
||||||
Run container in an existing pod
|
Run container in an existing pod. If you want podman to make the pod for you, preference the pod name with `new:`.
|
||||||
|
To make a pod with more granular options, use the `podman pod create` command before creating a container.
|
||||||
|
|
||||||
**--privileged**=*true*|*false*
|
**--privileged**=*true*|*false*
|
||||||
|
|
||||||
|
@ -439,7 +439,8 @@ Tune the container's pids limit. Set `-1` to have unlimited pids for the contain
|
|||||||
|
|
||||||
**--pod**=""
|
**--pod**=""
|
||||||
|
|
||||||
Run container in an existing pod
|
Run container in an existing pod. If you want podman to make the pod for you, preference the pod name with `new:`.
|
||||||
|
To make a pod with more granular options, use the `podman pod create` command before creating a container.
|
||||||
|
|
||||||
**--privileged**=*true*|*false*
|
**--privileged**=*true*|*false*
|
||||||
|
|
||||||
|
@ -496,8 +496,13 @@ func (c *CreateConfig) GetContainerCreateOptions(runtime *libpod.Runtime) ([]lib
|
|||||||
|
|
||||||
// CreatePortBindings iterates ports mappings and exposed ports into a format CNI understands
|
// CreatePortBindings iterates ports mappings and exposed ports into a format CNI understands
|
||||||
func (c *CreateConfig) CreatePortBindings() ([]ocicni.PortMapping, error) {
|
func (c *CreateConfig) CreatePortBindings() ([]ocicni.PortMapping, error) {
|
||||||
|
return NatToOCIPortBindings(c.PortBindings)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NatToOCIPortBindings iterates a nat.portmap slice and creates []ocicni portmapping slice
|
||||||
|
func NatToOCIPortBindings(ports nat.PortMap) ([]ocicni.PortMapping, error) {
|
||||||
var portBindings []ocicni.PortMapping
|
var portBindings []ocicni.PortMapping
|
||||||
for containerPb, hostPb := range c.PortBindings {
|
for containerPb, hostPb := range ports {
|
||||||
var pm ocicni.PortMapping
|
var pm ocicni.PortMapping
|
||||||
pm.ContainerPort = int32(containerPb.Int())
|
pm.ContainerPort = int32(containerPb.Int())
|
||||||
for _, i := range hostPb {
|
for _, i := range hostPb {
|
||||||
|
@ -189,4 +189,15 @@ var _ = Describe("Podman create", func() {
|
|||||||
Expect(session.ExitCode()).To(Equal(0))
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
Expect(session.OutputToString()).To(ContainSubstring("/create/test rw,nosuid,nodev,noexec,relatime - tmpfs"))
|
Expect(session.OutputToString()).To(ContainSubstring("/create/test rw,nosuid,nodev,noexec,relatime - tmpfs"))
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman create --pod automatically", func() {
|
||||||
|
session := podmanTest.Podman([]string{"create", "--pod", "new:foobar", ALPINE, "ls"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
|
check := podmanTest.Podman([]string{"pod", "ps", "--no-trunc"})
|
||||||
|
check.WaitWithDefaultTimeout()
|
||||||
|
match, _ := check.GrepString("foobar")
|
||||||
|
Expect(match).To(BeTrue())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
@ -628,4 +628,15 @@ USER mail`
|
|||||||
isSharedOnly := !strings.Contains(shared[0], "shared,")
|
isSharedOnly := !strings.Contains(shared[0], "shared,")
|
||||||
Expect(isSharedOnly).Should(BeTrue())
|
Expect(isSharedOnly).Should(BeTrue())
|
||||||
})
|
})
|
||||||
|
|
||||||
|
It("podman run --pod automatically", func() {
|
||||||
|
session := podmanTest.Podman([]string{"run", "--pod", "new:foobar", ALPINE, "ls"})
|
||||||
|
session.WaitWithDefaultTimeout()
|
||||||
|
Expect(session.ExitCode()).To(Equal(0))
|
||||||
|
|
||||||
|
check := podmanTest.Podman([]string{"pod", "ps", "--no-trunc"})
|
||||||
|
check.WaitWithDefaultTimeout()
|
||||||
|
match, _ := check.GrepString("foobar")
|
||||||
|
Expect(match).To(BeTrue())
|
||||||
|
})
|
||||||
})
|
})
|
||||||
|
Reference in New Issue
Block a user