Skip to content

Commit

Permalink
Allow namespace path network option for pods.
Browse files Browse the repository at this point in the history
Closes containers#16208.

Signed-off-by: Björn Mosler <[email protected]>
  • Loading branch information
Björn Mosler committed Nov 4, 2022
1 parent d319860 commit 049a5d8
Show file tree
Hide file tree
Showing 3 changed files with 228 additions and 3 deletions.
5 changes: 5 additions & 0 deletions pkg/specgen/generate/pod_create.go
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,11 @@ func MapSpec(p *specgen.PodSpecGenerator) (*specgen.SpecGenerator, error) {
p.InfraContainerSpec.NetworkOptions = p.NetworkOptions
p.InfraContainerSpec.NetNS.NSMode = specgen.Slirp
}
case specgen.Path:
logrus.Debugf("Pod will use namespace path networking")
p.InfraContainerSpec.NetNS.NSMode = specgen.Path
p.InfraContainerSpec.NetNS.Value = p.PodNetworkConfig.NetNS.Value

case specgen.NoNetwork:
logrus.Debugf("Pod will not use networking")
if len(p.InfraContainerSpec.PortMappings) > 0 ||
Expand Down
189 changes: 189 additions & 0 deletions pkg/specgen/generate/pod_create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package generate

import (
"net"

"github.com/containers/common/libnetwork/types"
"github.com/containers/podman/v4/pkg/specgen"
"github.com/stretchr/testify/assert"

"testing"
)

var (
portMappings = []types.PortMapping{{HostPort: 443, ContainerPort: 8080, Protocol: protoUDP}, {HostPort: 22, ContainerPort: 2222, Protocol: protoTCP}}
networks = map[string]types.PerNetworkOptions{"test": {
StaticIPs: nil,
Aliases: nil,
StaticMAC: nil,
InterfaceName: "eth2",
}}
)

func TestMapSpecCopyPodSpecToInfraContainerSpec(t *testing.T) {
infraCommand := []string{"top"}
addedHosts := []string{"otherhost"}
dnsServers := []net.IP{net.IPv4(10, 0, 0, 1), net.IPv4(8, 8, 8, 8)}
dnsOptions := []string{"dns option"}
dnsSearch := []string{"dns search"}
infraImage := "someimage"
conmonPidFile := "/var/run/conmon.pid"
podSpec := specgen.PodSpecGenerator{
PodBasicConfig: specgen.PodBasicConfig{InfraCommand: infraCommand, InfraImage: infraImage,
InfraConmonPidFile: conmonPidFile},
PodNetworkConfig: specgen.PodNetworkConfig{
PortMappings: portMappings, HostAdd: addedHosts, DNSServer: dnsServers, DNSOption: dnsOptions, DNSSearch: dnsSearch,
Networks: networks, NoManageResolvConf: true, NoManageHosts: true},
PodCgroupConfig: specgen.PodCgroupConfig{},
PodResourceConfig: specgen.PodResourceConfig{},
PodStorageConfig: specgen.PodStorageConfig{},
PodSecurityConfig: specgen.PodSecurityConfig{},
InfraContainerSpec: &specgen.SpecGenerator{},
ServiceContainerID: "",
}

mappedSpec, err := MapSpec(&podSpec)

assert.NoError(t, err)

assert.Equal(t, portMappings, mappedSpec.PortMappings)
assert.Equal(t, infraCommand, mappedSpec.Entrypoint)
assert.Equal(t, addedHosts, mappedSpec.HostAdd)
assert.Equal(t, dnsServers, mappedSpec.DNSServers)
assert.Equal(t, dnsOptions, mappedSpec.DNSOptions)
assert.Equal(t, dnsSearch, mappedSpec.DNSSearch)
assert.True(t, mappedSpec.UseImageResolvConf)
assert.Equal(t, networks, mappedSpec.Networks)
assert.True(t, mappedSpec.UseImageHosts)
assert.Equal(t, conmonPidFile, mappedSpec.ConmonPidFile)
assert.Equal(t, infraImage, mappedSpec.Image)
}

func createPodSpec(mode specgen.NamespaceMode) specgen.PodSpecGenerator {
return specgen.PodSpecGenerator{
InfraContainerSpec: &specgen.SpecGenerator{},
PodNetworkConfig: specgen.PodNetworkConfig{
NetNS: specgen.Namespace{NSMode: mode},
},
}
}

func createPodSpecWithNetworks(mode specgen.NamespaceMode) specgen.PodSpecGenerator {
spec := createPodSpec(mode)
spec.InfraContainerSpec.Networks = networks
return spec
}

func createPodSpecWithPortMapping(mode specgen.NamespaceMode) specgen.PodSpecGenerator {
spec := createPodSpec(mode)
spec.InfraContainerSpec.PortMappings = portMappings
return spec
}

func createPodSpecWithNetNsPath(path string) specgen.PodSpecGenerator {
spec := createPodSpec(specgen.Path)
spec.NetNS.Value = path
return spec
}

func TestMapSpecNetworkOptions(t *testing.T) {
tests := []struct {
name string
podSpec specgen.PodSpecGenerator
expectedNSMode specgen.NamespaceMode
expectedNSValue string
expectedNetworkOptions map[string][]string
mustError bool
}{
{
name: "Default",
podSpec: createPodSpec(specgen.Default),
expectedNSMode: "",
},
{
name: "Bridge",
podSpec: createPodSpec(specgen.Bridge),
expectedNSMode: specgen.Bridge,
},
{
name: "Private",
podSpec: createPodSpec(specgen.Private),
expectedNSMode: specgen.Private,
}, {
name: "Host",
podSpec: createPodSpec(specgen.Host),
expectedNSMode: specgen.Host,
},
{
name: "Host but with port mappings",
podSpec: createPodSpecWithPortMapping(specgen.Host),
mustError: true,
}, {
name: "Host but with networks",
podSpec: createPodSpecWithNetworks(specgen.Host),
mustError: true,
},
{
name: "Slirp",
podSpec: createPodSpec(specgen.Slirp),
expectedNSMode: specgen.Slirp,
},
{
name: "Slirp but if infra spec NS mode is Host",
podSpec: specgen.PodSpecGenerator{
InfraContainerSpec: &specgen.SpecGenerator{
ContainerNetworkConfig: specgen.ContainerNetworkConfig{NetNS: specgen.Namespace{NSMode: host}},
},
PodNetworkConfig: specgen.PodNetworkConfig{
NetNS: specgen.Namespace{NSMode: specgen.Slirp},
},
},
expectedNSMode: specgen.Host,
},
{
name: "Path",
podSpec: createPodSpecWithNetNsPath("/var/run/netns/bla"),
expectedNSMode: specgen.Path,
expectedNSValue: "/var/run/netns/bla",
},
{
name: "NoNetwork",
podSpec: createPodSpec(specgen.NoNetwork),
expectedNSMode: specgen.NoNetwork,
},
{
name: "NoNetwork but with networks",
podSpec: createPodSpecWithNetworks(specgen.NoNetwork),
mustError: true,
},
{
name: "NoNetwork but with port mappings",
podSpec: createPodSpecWithPortMapping(specgen.NoNetwork),
mustError: true,
},
{
name: "FromContainer",
podSpec: createPodSpec(specgen.FromContainer),
mustError: true,
}, {
name: "FromPod",
podSpec: createPodSpec(specgen.FromPod),
mustError: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mappedSpec, err := MapSpec(&tt.podSpec)

if tt.mustError {
assert.Error(t, err)
} else {
assert.NoError(t, err, "error is not nil")
assert.Equal(t, tt.expectedNSMode, mappedSpec.NetNS.NSMode)
assert.Equal(t, tt.expectedNSValue, mappedSpec.NetNS.Value)
assert.Equal(t, tt.expectedNetworkOptions, mappedSpec.NetworkOptions)
}
})
}
}
37 changes: 34 additions & 3 deletions test/e2e/pod_create_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -500,11 +500,42 @@ entrypoint ["/fromimage"]
podCreate.WaitWithDefaultTimeout()
Expect(podCreate).Should(Exit(125))
Expect(podCreate.ErrorToString()).To(ContainSubstring("pods presently do not support network mode container"))
})

It("podman pod create with namespace path networking", func() {
SkipIfRootless("ip netns is not supported for rootless users")
SkipIfContainerized("ip netns cannot be run within a container.")

podName := "netnspod"
netNsName := "test1"
networkMode := fmt.Sprintf("ns:/var/run/netns/%s", netNsName)

podCreate = podmanTest.Podman([]string{"pod", "create", "--network", "ns:/does/not/matter"})
addNetns := SystemExec("ip", []string{"netns", "add", netNsName})
Expect(addNetns).Should(Exit(0))
defer func() {
delNetns := SystemExec("ip", []string{"netns", "delete", netNsName})
Expect(delNetns).Should(Exit(0))
}()

podCreate := podmanTest.Podman([]string{"pod", "create", "--name", podName, "--network", networkMode})
podCreate.WaitWithDefaultTimeout()
Expect(podCreate).Should(Exit(125))
Expect(podCreate.ErrorToString()).To(ContainSubstring("pods presently do not support network mode path"))
Expect(podCreate).Should(Exit(0))

podStart := podmanTest.Podman([]string{"pod", "start", podName})
podStart.WaitWithDefaultTimeout()
Expect(podStart).Should(Exit(0))

inspectPod := podmanTest.Podman([]string{"pod", "inspect", podName})
inspectPod.WaitWithDefaultTimeout()
Expect(inspectPod).Should(Exit(0))
inspectPodJSON := inspectPod.InspectPodToJSON()

inspectInfraContainer := podmanTest.Podman([]string{"inspect", inspectPodJSON.InfraContainerID})
inspectInfraContainer.WaitWithDefaultTimeout()
Expect(inspectInfraContainer).Should(Exit(0))
inspectInfraContainerJSON := inspectInfraContainer.InspectContainerToJSON()

Expect(inspectInfraContainerJSON[0].HostConfig.NetworkMode).To(Equal(networkMode))
})

It("podman pod create with --net=none", func() {
Expand Down

0 comments on commit 049a5d8

Please sign in to comment.