Skip to content

Commit

Permalink
Merge pull request #9237 from mheon/backports_300_RC3
Browse files Browse the repository at this point in the history
Backports for v3.0,0-RC3
  • Loading branch information
openshift-merge-robot authored Feb 5, 2021
2 parents 9e2cdc4 + c5c946b commit 288fb68
Show file tree
Hide file tree
Showing 55 changed files with 1,242 additions and 468 deletions.
359 changes: 161 additions & 198 deletions RELEASE_NOTES.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions cmd/podman/common/completion.go
Original file line number Diff line number Diff line change
Expand Up @@ -817,6 +817,7 @@ func AutocompleteNetworkFlag(cmd *cobra.Command, args []string, toComplete strin
"allow_host_loopback=": getBoolCompletion,
"cidr=": nil,
"enable_ipv6=": getBoolCompletion,
"mtu=": nil,
"outbound_addr=": nil,
"outbound_addr6=": nil,
"port_handler=": func(_ string) ([]string, cobra.ShellCompDirective) {
Expand Down
16 changes: 16 additions & 0 deletions cmd/podman/common/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,10 @@ func getBindMount(args []string) (spec.Mount, error) {
default:
return newMount, errors.Wrapf(util.ErrBadMntOption, "%s mount option must be 'private' or 'shared'", kv[0])
}
case "consistency":
// Often used on MACs and mistakenly on Linux platforms.
// Since Docker ignores this option so shall we.
continue
default:
return newMount, errors.Wrapf(util.ErrBadMntOption, kv[0])
}
Expand Down Expand Up @@ -437,6 +441,10 @@ func getTmpfsMount(args []string) (spec.Mount, error) {
}
newMount.Destination = filepath.Clean(kv[1])
setDest = true
case "consistency":
// Often used on MACs and mistakenly on Linux platforms.
// Since Docker ignores this option so shall we.
continue
default:
return newMount, errors.Wrapf(util.ErrBadMntOption, kv[0])
}
Expand Down Expand Up @@ -534,6 +542,10 @@ func getNamedVolume(args []string) (*specgen.NamedVolume, error) {
}
newVolume.Dest = filepath.Clean(kv[1])
setDest = true
case "consistency":
// Often used on MACs and mistakenly on Linux platforms.
// Since Docker ignores this option so shall we.
continue
default:
return nil, errors.Wrapf(util.ErrBadMntOption, kv[0])
}
Expand Down Expand Up @@ -581,6 +593,10 @@ func getImageVolume(args []string) (*specgen.ImageVolume, error) {
default:
return nil, errors.Wrapf(util.ErrBadMntOption, "invalid rw value %q", kv[1])
}
case "consistency":
// Often used on MACs and mistakenly on Linux platforms.
// Since Docker ignores this option so shall we.
continue
default:
return nil, errors.Wrapf(util.ErrBadMntOption, kv[0])
}
Expand Down
27 changes: 0 additions & 27 deletions cmd/podman/pods/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -171,33 +171,6 @@ func create(cmd *cobra.Command, args []string) error {
if err != nil {
return err
}
createOptions.Net.Network = specgen.Namespace{}
if cmd.Flag("network").Changed {
netInput, err := cmd.Flags().GetString("network")
if err != nil {
return err
}
parts := strings.SplitN(netInput, ":", 2)

n := specgen.Namespace{}
switch {
case netInput == "bridge":
n.NSMode = specgen.Bridge
case netInput == "host":
n.NSMode = specgen.Host
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
createOptions.Net.CNINetworks = strings.Split(netInput, ",")
}
createOptions.Net.Network = n
}
if len(createOptions.Net.PublishPorts) > 0 {
if !createOptions.Infra {
return errors.Errorf("you must have an infra container to publish port bindings to the host")
Expand Down
1 change: 1 addition & 0 deletions docs/source/markdown/podman-create.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -635,6 +635,7 @@ Valid _mode_ values are:
- **private**: create a new namespace for the container (default)
- **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) 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.
- **mtu=MTU**: Specify the MTU to use for this network. (Default is `65520`).
- **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).
Expand Down
1 change: 1 addition & 0 deletions docs/source/markdown/podman-run.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -671,6 +671,7 @@ Valid _mode_ values are:
- **private**: create a new namespace for the container (default)
- **slirp4netns[:OPTIONS,...]**: use **slirp4netns**(1) 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.
- **mtu=MTU**: Specify the MTU to use for this network. (Default is `65520`).
- **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).
Expand Down
12 changes: 12 additions & 0 deletions libpod/container.go
Original file line number Diff line number Diff line change
Expand Up @@ -1073,6 +1073,18 @@ func networkDisabled(c *Container) (bool, error) {
return false, nil
}

func (c *Container) HostNetwork() bool {
if c.config.CreateNetNS || c.config.NetNsCtr != "" {
return false
}
for _, ns := range c.config.Spec.Linux.Namespaces {
if ns.Type == spec.NetworkNamespace {
return false
}
}
return true
}

// ContainerState returns containerstate struct
func (c *Container) ContainerState() (*ContainerState, error) {
if !c.batched {
Expand Down
1 change: 1 addition & 0 deletions libpod/container_internal_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,7 @@ func (c *Container) resolveWorkDir() error {
// we need to return the full error.
return errors.Wrapf(err, "error detecting workdir %q on container %s", workdir, c.ID())
}
return nil
}

// Ensure container entrypoint is created (if required).
Expand Down
149 changes: 119 additions & 30 deletions libpod/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
}

extraHost := make([]v1.HostAlias, 0)
hostNetwork := false
if p.HasInfraContainer() {
infraContainer, err := p.getInfraContainer()
if err != nil {
Expand All @@ -69,9 +70,9 @@ func (p *Pod) GenerateForKube() (*v1.Pod, []v1.ServicePort, error) {
return nil, servicePorts, err
}
servicePorts = containerPortsToServicePorts(ports)

hostNetwork = p.config.InfraContainer.HostNetwork
}
pod, err := p.podWithContainers(allContainers, ports)
pod, err := p.podWithContainers(allContainers, ports, hostNetwork)
if err != nil {
return nil, servicePorts, err
}
Expand Down Expand Up @@ -167,13 +168,14 @@ func containersToServicePorts(containers []v1.Container) []v1.ServicePort {
return sps
}

func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPort) (*v1.Pod, error) {
func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPort, hostNetwork bool) (*v1.Pod, error) {
deDupPodVolumes := make(map[string]*v1.Volume)
first := true
podContainers := make([]v1.Container, 0, len(containers))
dnsInfo := v1.PodDNSConfig{}
for _, ctr := range containers {
if !ctr.IsInfra() {
ctr, volumes, err := containerToV1Container(ctr)
ctr, volumes, _, err := containerToV1Container(ctr)
if err != nil {
return nil, err
}
Expand All @@ -196,17 +198,33 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor
vol := vol
deDupPodVolumes[vol.Name] = &vol
}
} else {
_, _, infraDNS, err := containerToV1Container(ctr)
if err != nil {
return nil, err
}
if infraDNS != nil {
if servers := infraDNS.Nameservers; len(servers) > 0 {
dnsInfo.Nameservers = servers
}
if searches := infraDNS.Searches; len(searches) > 0 {
dnsInfo.Searches = searches
}
if options := infraDNS.Options; len(options) > 0 {
dnsInfo.Options = options
}
}
}
}
podVolumes := make([]v1.Volume, 0, len(deDupPodVolumes))
for _, vol := range deDupPodVolumes {
podVolumes = append(podVolumes, *vol)
}

return addContainersAndVolumesToPodObject(podContainers, podVolumes, p.Name()), nil
return addContainersAndVolumesToPodObject(podContainers, podVolumes, p.Name(), &dnsInfo, hostNetwork), nil
}

func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1.Volume, podName string) *v1.Pod {
func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1.Volume, podName string, dnsOptions *v1.PodDNSConfig, hostNetwork bool) *v1.Pod {
tm := v12.TypeMeta{
Kind: "Pod",
APIVersion: "v1",
Expand All @@ -225,8 +243,12 @@ func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1.
CreationTimestamp: v12.Now(),
}
ps := v1.PodSpec{
Containers: containers,
Volumes: volumes,
Containers: containers,
Volumes: volumes,
HostNetwork: hostNetwork,
}
if dnsOptions != nil {
ps.DNSConfig = dnsOptions
}
p := v1.Pod{
TypeMeta: tm,
Expand All @@ -241,75 +263,111 @@ func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1.
func simplePodWithV1Containers(ctrs []*Container) (*v1.Pod, error) {
kubeCtrs := make([]v1.Container, 0, len(ctrs))
kubeVolumes := make([]v1.Volume, 0)
hostNetwork := true
podDNS := v1.PodDNSConfig{}
for _, ctr := range ctrs {
kubeCtr, kubeVols, err := containerToV1Container(ctr)
if !ctr.HostNetwork() {
hostNetwork = false
}
kubeCtr, kubeVols, ctrDNS, err := containerToV1Container(ctr)
if err != nil {
return nil, err
}
kubeCtrs = append(kubeCtrs, kubeCtr)
kubeVolumes = append(kubeVolumes, kubeVols...)
}
return addContainersAndVolumesToPodObject(kubeCtrs, kubeVolumes, strings.ReplaceAll(ctrs[0].Name(), "_", "")), nil

// Combine DNS information in sum'd structure
if ctrDNS != nil {
// nameservers
if servers := ctrDNS.Nameservers; servers != nil {
if podDNS.Nameservers == nil {
podDNS.Nameservers = make([]string, 0)
}
for _, s := range servers {
if !util.StringInSlice(s, podDNS.Nameservers) { // only append if it does not exist
podDNS.Nameservers = append(podDNS.Nameservers, s)
}
}
}
// search domains
if domains := ctrDNS.Searches; domains != nil {
if podDNS.Searches == nil {
podDNS.Searches = make([]string, 0)
}
for _, d := range domains {
if !util.StringInSlice(d, podDNS.Searches) { // only append if it does not exist
podDNS.Searches = append(podDNS.Searches, d)
}
}
}
// dns options
if options := ctrDNS.Options; options != nil {
if podDNS.Options == nil {
podDNS.Options = make([]v1.PodDNSConfigOption, 0)
}
podDNS.Options = append(podDNS.Options, options...)
}
} // end if ctrDNS
}
return addContainersAndVolumesToPodObject(kubeCtrs, kubeVolumes, strings.ReplaceAll(ctrs[0].Name(), "_", ""), &podDNS, hostNetwork), nil
}

// containerToV1Container converts information we know about a libpod container
// to a V1.Container specification.
func containerToV1Container(c *Container) (v1.Container, []v1.Volume, error) {
func containerToV1Container(c *Container) (v1.Container, []v1.Volume, *v1.PodDNSConfig, error) {
kubeContainer := v1.Container{}
kubeVolumes := []v1.Volume{}
kubeSec, err := generateKubeSecurityContext(c)
if err != nil {
return kubeContainer, kubeVolumes, err
return kubeContainer, kubeVolumes, nil, err
}

if len(c.config.Spec.Linux.Devices) > 0 {
// TODO Enable when we can support devices and their names
kubeContainer.VolumeDevices = generateKubeVolumeDeviceFromLinuxDevice(c.Spec().Linux.Devices)
return kubeContainer, kubeVolumes, errors.Wrapf(define.ErrNotImplemented, "linux devices")
return kubeContainer, kubeVolumes, nil, errors.Wrapf(define.ErrNotImplemented, "linux devices")
}

if len(c.config.UserVolumes) > 0 {
// TODO When we until we can resolve what the volume name should be, this is disabled
// Volume names need to be coordinated "globally" in the kube files.
volumeMounts, volumes, err := libpodMountsToKubeVolumeMounts(c)
if err != nil {
return kubeContainer, kubeVolumes, err
return kubeContainer, kubeVolumes, nil, err
}
kubeContainer.VolumeMounts = volumeMounts
kubeVolumes = append(kubeVolumes, volumes...)
}

envVariables, err := libpodEnvVarsToKubeEnvVars(c.config.Spec.Process.Env)
if err != nil {
return kubeContainer, kubeVolumes, err
return kubeContainer, kubeVolumes, nil, err
}

portmappings, err := c.PortMappings()
if err != nil {
return kubeContainer, kubeVolumes, err
return kubeContainer, kubeVolumes, nil, err
}
ports, err := ocicniPortMappingToContainerPort(portmappings)
if err != nil {
return kubeContainer, kubeVolumes, err
return kubeContainer, kubeVolumes, nil, err
}

containerCommands := c.Command()
kubeContainer.Name = removeUnderscores(c.Name())
// Handle command and arguments.
if ep := c.Entrypoint(); len(ep) > 0 {
// If we have an entrypoint, set the container's command as
// arguments.
kubeContainer.Command = ep
kubeContainer.Args = c.Command()
} else {
kubeContainer.Command = c.Command()
}

kubeContainer.Name = removeUnderscores(c.Name())
_, image := c.Image()
kubeContainer.Image = image
kubeContainer.Stdin = c.Stdin()

// prepend the entrypoint of the container to command
if ep := c.Entrypoint(); len(c.Entrypoint()) > 0 {
ep = append(ep, containerCommands...)
containerCommands = ep
}
kubeContainer.Command = containerCommands
// TODO need to figure out how we handle command vs entry point. Kube appears to prefer entrypoint.
// right now we just take the container's command
//container.Args = args
kubeContainer.WorkingDir = c.WorkingDir()
kubeContainer.Ports = ports
// This should not be applicable
Expand Down Expand Up @@ -355,7 +413,38 @@ func containerToV1Container(c *Container) (v1.Container, []v1.Volume, error) {
}
}

return kubeContainer, kubeVolumes, nil
// Obtain the DNS entries from the container
dns := v1.PodDNSConfig{}

// DNS servers
if servers := c.config.DNSServer; len(servers) > 0 {
dnsServers := make([]string, 0)
for _, server := range servers {
dnsServers = append(dnsServers, server.String())
}
dns.Nameservers = dnsServers
}

// DNS search domains
if searches := c.config.DNSSearch; len(searches) > 0 {
dns.Searches = searches
}

// DNS options
if options := c.config.DNSOption; len(options) > 0 {
dnsOptions := make([]v1.PodDNSConfigOption, 0)
for _, option := range options {
// the option can be "k:v" or just "k", no delimiter is required
opts := strings.SplitN(option, ":", 2)
dnsOpt := v1.PodDNSConfigOption{
Name: opts[0],
Value: &opts[1],
}
dnsOptions = append(dnsOptions, dnsOpt)
}
dns.Options = dnsOptions
}
return kubeContainer, kubeVolumes, &dns, nil
}

// ocicniPortMappingToContainerPort takes an ocicni portmapping and converts
Expand Down
Loading

0 comments on commit 288fb68

Please sign in to comment.