diff options
| -rw-r--r-- | cmd/podman/pods/create.go | 14 | ||||
| -rw-r--r-- | docs/source/markdown/podman-pod-create.1.md | 19 | ||||
| -rw-r--r-- | libpod/define/pod_inspect.go | 2 | ||||
| -rw-r--r-- | libpod/options.go | 20 | ||||
| -rw-r--r-- | libpod/pod.go | 2 | ||||
| -rw-r--r-- | libpod/pod_api.go | 2 | ||||
| -rw-r--r-- | libpod/runtime_pod_infra_linux.go | 5 | ||||
| -rw-r--r-- | pkg/domain/entities/pods.go | 1 | ||||
| -rw-r--r-- | pkg/specgen/generate/pod_create.go | 3 | ||||
| -rw-r--r-- | pkg/specgen/pod_validate.go | 4 | ||||
| -rw-r--r-- | pkg/specgen/podspecgen.go | 3 | ||||
| -rw-r--r-- | test/e2e/pod_create_test.go | 12 | 
12 files changed, 78 insertions, 9 deletions
diff --git a/cmd/podman/pods/create.go b/cmd/podman/pods/create.go index d8d32b930..ac6d83edd 100644 --- a/cmd/podman/pods/create.go +++ b/cmd/podman/pods/create.go @@ -141,14 +141,20 @@ func create(cmd *cobra.Command, args []string) error {  		if err != nil {  			return err  		} +		parts := strings.SplitN(netInput, ":", 2) +  		n := specgen.Namespace{} -		switch netInput { -		case "bridge": +		switch { +		case netInput == "bridge":  			n.NSMode = specgen.Bridge -		case "host": +		case netInput == "host":  			n.NSMode = specgen.Host -		case "slirp4netns": +		case netInput == "slirp4netns", strings.HasPrefix(netInput, "slirp4netns:"):  			n.NSMode = specgen.Slirp +			if len(parts) > 1 { +				createOptions.Net.NetworkOptions = make(map[string][]string) +				createOptions.Net.NetworkOptions[parts[0]] = strings.Split(parts[1], ",") +			}  		default:  			// Container and NS mode are presently unsupported  			n.NSMode = specgen.Bridge diff --git a/docs/source/markdown/podman-pod-create.1.md b/docs/source/markdown/podman-pod-create.1.md index d60fc65fe..7b0902c19 100644 --- a/docs/source/markdown/podman-pod-create.1.md +++ b/docs/source/markdown/podman-pod-create.1.md @@ -81,7 +81,20 @@ Assign a name to the pod.  **--network**=*mode* -Set network mode for the pod. Supported values are *bridge* (the default), *host* (do not create a network namespace, all containers in the pod will use the host's network), or a comma-separated list of the names of CNI networks the pod should join. +Set network mode for the pod. Supported values are +- `bridge`: Create a network stack on the default bridge. This is the default for rootful containers. +- `host`: Do not create a network namespace, all containers in the pod will use the host's network. Note: the host mode gives the container full access to local system services such as D-bus and is therefore considered insecure. +- Comma-separated list of the names of CNI networks the pod should join. +- `slirp4netns[:OPTIONS,...]`: use slirp4netns to create a user network stack.  This is the default for rootless containers.  It is possible to specify these additional options: +  - **allow_host_loopback=true|false**: Allow the slirp4netns to reach the host loopback IP (`10.0.2.2`). Default is false. +  - **cidr=CIDR**: Specify ip range to use for this network. (Default is `10.0.2.0/24`). +  - **enable_ipv6=true|false**: Enable IPv6. Default is false. (Required for `outbound_addr6`). +  - **outbound_addr=INTERFACE**: Specify the outbound interface slirp should bind to (ipv4 traffic only). +  - **outbound_addr=IPv4**: Specify the outbound ipv4 address slirp should bind to. +  - **outbound_addr6=INTERFACE**: Specify the outbound interface slirp should bind to (ipv6 traffic only). +  - **outbound_addr6=IPv6**: Specify the outbound ipv6 address slirp should bind to. +  - **port_handler=rootlesskit**: Use rootlesskit for port forwarding. Default. +  - **port_handler=slirp4netns**: Use the slirp4netns port forwarding.  **--no-hosts**=**true**|**false** @@ -129,6 +142,10 @@ $ podman pod create --infra=false  $ podman pod create --infra-command /top  $ podman pod create --publish 8443:443 + +$ podman pod create --network slirp4netns:outbound_addr=127.0.0.1,allow_host_loopback=true + +$ podman pod create --network slirp4netns:cidr=192.168.0.0/24  ```  ## SEE ALSO diff --git a/libpod/define/pod_inspect.go b/libpod/define/pod_inspect.go index 60e19fe05..a4115eb92 100644 --- a/libpod/define/pod_inspect.go +++ b/libpod/define/pod_inspect.go @@ -89,6 +89,8 @@ type InspectPodInfraConfig struct {  	HostAdd []string  	// Networks is a list of CNI networks the pod will join.  	Networks []string +	// NetworkOptions are additional options for each network +	NetworkOptions map[string][]string  }  // InspectPodContainerInfo contains information on a container in a pod. diff --git a/libpod/options.go b/libpod/options.go index f7b3419e5..f7190d0e3 100644 --- a/libpod/options.go +++ b/libpod/options.go @@ -2203,3 +2203,23 @@ func WithPodInfraExitCommand(exitCmd []string) PodCreateOption {  		return nil  	}  } + +// WithPodSlirp4netns tells the pod to use slirp4netns. +func WithPodSlirp4netns(networkOptions map[string][]string) PodCreateOption { +	return func(pod *Pod) error { +		if pod.valid { +			return define.ErrPodFinalized +		} + +		if !pod.config.InfraContainer.HasInfraContainer { +			return errors.Wrapf(define.ErrInvalidArg, "cannot configure pod networking as no infra container is being created") +		} +		if pod.config.InfraContainer.HostNetwork { +			return errors.Wrapf(define.ErrInvalidArg, "cannot set both HostNetwork and Slirp4netns") +		} +		pod.config.InfraContainer.Slirp4netns = true +		pod.config.InfraContainer.NetworkOptions = networkOptions + +		return nil +	} +} diff --git a/libpod/pod.go b/libpod/pod.go index 709184008..a5a0532be 100644 --- a/libpod/pod.go +++ b/libpod/pod.go @@ -107,6 +107,8 @@ type InfraContainerConfig struct {  	ExitCommand        []string             `json:"exitCommand,omitempty"`  	InfraImage         string               `json:"infraImage,omitempty"`  	InfraCommand       []string             `json:"infraCommand,omitempty"` +	Slirp4netns        bool                 `json:"slirp4netns,omitempty"` +	NetworkOptions     map[string][]string  `json:"network_options,omitempty"`  }  // ID retrieves the pod's ID diff --git a/libpod/pod_api.go b/libpod/pod_api.go index ec4cc08f7..0ae180356 100644 --- a/libpod/pod_api.go +++ b/libpod/pod_api.go @@ -584,7 +584,7 @@ func (p *Pod) Inspect() (*define.InspectPodData, error) {  			infraConfig.Networks = make([]string, 0, len(p.config.InfraContainer.Networks))  			infraConfig.Networks = append(infraConfig.Networks, p.config.InfraContainer.Networks...)  		} - +		infraConfig.NetworkOptions = p.config.InfraContainer.NetworkOptions  		infraConfig.PortBindings = makeInspectPortBindings(p.config.InfraContainer.PortBindings)  	} diff --git a/libpod/runtime_pod_infra_linux.go b/libpod/runtime_pod_infra_linux.go index 570cdd38f..7f58e86d8 100644 --- a/libpod/runtime_pod_infra_linux.go +++ b/libpod/runtime_pod_infra_linux.go @@ -81,8 +81,11 @@ func (r *Runtime) makeInfraContainer(ctx context.Context, p *Pod, imgName, rawIm  		// Since user namespace sharing is not implemented, we only need to check if it's rootless  		if !p.config.InfraContainer.HostNetwork {  			netmode := "bridge" -			if isRootless { +			if isRootless || p.config.InfraContainer.Slirp4netns {  				netmode = "slirp4netns" +				if len(p.config.InfraContainer.NetworkOptions) != 0 { +					options = append(options, WithNetworkOptions(p.config.InfraContainer.NetworkOptions)) +				}  			}  			// PostConfigureNetNS should not be set since user namespace sharing is not implemented  			// and rootless networking no longer supports post configuration setup diff --git a/pkg/domain/entities/pods.go b/pkg/domain/entities/pods.go index 7b38dbd87..426419833 100644 --- a/pkg/domain/entities/pods.go +++ b/pkg/domain/entities/pods.go @@ -142,6 +142,7 @@ func (p PodCreateOptions) ToPodSpecGen(s *specgen.PodSpecGenerator) {  	s.StaticMAC = p.Net.StaticMAC  	s.PortMappings = p.Net.PublishPorts  	s.CNINetworks = p.Net.CNINetworks +	s.NetworkOptions = p.Net.NetworkOptions  	if p.Net.UseImageResolvConf {  		s.NoManageResolvConf = true  	} diff --git a/pkg/specgen/generate/pod_create.go b/pkg/specgen/generate/pod_create.go index 101201252..43caf0fe9 100644 --- a/pkg/specgen/generate/pod_create.go +++ b/pkg/specgen/generate/pod_create.go @@ -99,6 +99,9 @@ func createPodOptions(p *specgen.PodSpecGenerator, rt *libpod.Runtime) ([]libpod  	case specgen.Host:  		logrus.Debugf("Pod will use host networking")  		options = append(options, libpod.WithPodHostNetwork()) +	case specgen.Slirp: +		logrus.Debugf("Pod will use slirp4netns") +		options = append(options, libpod.WithPodSlirp4netns(p.NetworkOptions))  	default:  		return nil, errors.Errorf("pods presently do not support network mode %s", p.NetNS.NSMode)  	} diff --git a/pkg/specgen/pod_validate.go b/pkg/specgen/pod_validate.go index 907c0bb69..a6c61a203 100644 --- a/pkg/specgen/pod_validate.go +++ b/pkg/specgen/pod_validate.go @@ -72,9 +72,9 @@ func (p *PodSpecGenerator) Validate() error {  			return exclusivePodOptions("NoInfra", "NoManageResolvConf")  		}  	} -	if p.NetNS.NSMode != "" && p.NetNS.NSMode != Bridge && p.NetNS.NSMode != Default { +	if p.NetNS.NSMode != "" && p.NetNS.NSMode != Bridge && p.NetNS.NSMode != Slirp && p.NetNS.NSMode != Default {  		if len(p.PortMappings) > 0 { -			return errors.New("PortMappings can only be used with Bridge mode networking") +			return errors.New("PortMappings can only be used with Bridge or slirp4netns networking")  		}  		if len(p.CNINetworks) > 0 {  			return errors.New("CNINetworks can only be used with Bridge mode networking") diff --git a/pkg/specgen/podspecgen.go b/pkg/specgen/podspecgen.go index 3c32ec365..7d771f5bb 100644 --- a/pkg/specgen/podspecgen.go +++ b/pkg/specgen/podspecgen.go @@ -134,6 +134,9 @@ type PodNetworkConfig struct {  	// Conflicts with NoInfra=true and NoManageHosts.  	// Optional.  	HostAdd []string `json:"hostadd,omitempty"` +	// NetworkOptions are additional options for each network +	// Optional. +	NetworkOptions map[string][]string `json:"network_options,omitempty"`  }  // PodCgroupConfig contains configuration options about a pod's cgroups. diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go index ce0b51517..f69b6ca7b 100644 --- a/test/e2e/pod_create_test.go +++ b/test/e2e/pod_create_test.go @@ -416,4 +416,16 @@ entrypoint ["/fromimage"]  		Expect(check2.ExitCode()).To(Equal(0))  		Expect(check2.OutputToString()).To(Equal("/fromcommand:[/fromcommand]"))  	}) + +	It("podman create pod with slirp network option", func() { +		name := "test" +		session := podmanTest.Podman([]string{"pod", "create", "--name", name, "--network", "slirp4netns:port_handler=slirp4netns", "-p", "8082:8000"}) +		session.WaitWithDefaultTimeout() +		Expect(session.ExitCode()).To(Equal(0)) + +		check := podmanTest.Podman([]string{"pod", "inspect", "--format", "{{.InfraConfig.NetworkOptions.slirp4netns}}", name}) +		check.WaitWithDefaultTimeout() +		Expect(check.ExitCode()).To(Equal(0)) +		Expect(check.OutputToString()).To(Equal("[port_handler=slirp4netns]")) +	})  })  | 
