mirror of
https://github.com/containers/podman.git
synced 2025-06-17 15:08:08 +08:00
Merge pull request #9150 from baude/playkubedns
Honor custom DNS in play|generate kube
This commit is contained in:
112
libpod/kube.go
112
libpod/kube.go
@ -171,9 +171,10 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor
|
||||
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
|
||||
}
|
||||
@ -196,6 +197,22 @@ 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))
|
||||
@ -203,10 +220,10 @@ func (p *Pod) podWithContainers(containers []*Container, ports []v1.ContainerPor
|
||||
podVolumes = append(podVolumes, *vol)
|
||||
}
|
||||
|
||||
return addContainersAndVolumesToPodObject(podContainers, podVolumes, p.Name()), nil
|
||||
return addContainersAndVolumesToPodObject(podContainers, podVolumes, p.Name(), &dnsInfo), 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) *v1.Pod {
|
||||
tm := v12.TypeMeta{
|
||||
Kind: "Pod",
|
||||
APIVersion: "v1",
|
||||
@ -228,6 +245,9 @@ func addContainersAndVolumesToPodObject(containers []v1.Container, volumes []v1.
|
||||
Containers: containers,
|
||||
Volumes: volumes,
|
||||
}
|
||||
if dnsOptions != nil {
|
||||
ps.DNSConfig = dnsOptions
|
||||
}
|
||||
p := v1.Pod{
|
||||
TypeMeta: tm,
|
||||
ObjectMeta: om,
|
||||
@ -241,32 +261,65 @@ 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)
|
||||
podDNS := v1.PodDNSConfig{}
|
||||
for _, ctr := range ctrs {
|
||||
kubeCtr, kubeVols, err := containerToV1Container(ctr)
|
||||
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), 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 {
|
||||
@ -274,7 +327,7 @@ func containerToV1Container(c *Container) (v1.Container, []v1.Volume, error) {
|
||||
// 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...)
|
||||
@ -282,16 +335,16 @@ func containerToV1Container(c *Container) (v1.Container, []v1.Volume, error) {
|
||||
|
||||
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()
|
||||
@ -355,7 +408,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
|
||||
|
@ -3,6 +3,7 @@ package kube
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
|
||||
"github.com/containers/common/pkg/parse"
|
||||
@ -44,6 +45,31 @@ func ToPodGen(ctx context.Context, podName string, podYAML *v1.PodTemplateSpec)
|
||||
podPorts := getPodPorts(podYAML.Spec.Containers)
|
||||
p.PortMappings = podPorts
|
||||
|
||||
if dnsConfig := podYAML.Spec.DNSConfig; dnsConfig != nil {
|
||||
// name servers
|
||||
if dnsServers := dnsConfig.Nameservers; len(dnsServers) > 0 {
|
||||
servers := make([]net.IP, 0)
|
||||
for _, server := range dnsServers {
|
||||
servers = append(servers, net.ParseIP(server))
|
||||
}
|
||||
p.DNSServer = servers
|
||||
}
|
||||
// search domans
|
||||
if domains := dnsConfig.Searches; len(domains) > 0 {
|
||||
p.DNSSearch = domains
|
||||
}
|
||||
// dns options
|
||||
if options := dnsConfig.Options; len(options) > 0 {
|
||||
dnsOptions := make([]string, 0)
|
||||
for _, opts := range options {
|
||||
d := opts.Name
|
||||
if opts.Value != nil {
|
||||
d += ":" + *opts.Value
|
||||
}
|
||||
dnsOptions = append(dnsOptions, d)
|
||||
}
|
||||
}
|
||||
}
|
||||
return p, nil
|
||||
}
|
||||
|
||||
|
@ -540,4 +540,67 @@ var _ = Describe("Podman generate kube", func() {
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube.ExitCode()).ToNot(Equal(0))
|
||||
})
|
||||
|
||||
It("podman generate kube on a container with dns options", func() {
|
||||
top := podmanTest.Podman([]string{"run", "-dt", "--name", "top", "--dns", "8.8.8.8", "--dns-search", "foobar.com", "--dns-opt", "color:blue", ALPINE, "top"})
|
||||
top.WaitWithDefaultTimeout()
|
||||
Expect(top.ExitCode()).To(BeZero())
|
||||
|
||||
kube := podmanTest.Podman([]string{"generate", "kube", "top"})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube.ExitCode()).To(Equal(0))
|
||||
|
||||
pod := new(v1.Pod)
|
||||
err := yaml.Unmarshal(kube.Out.Contents(), pod)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
Expect(StringInSlice("8.8.8.8", pod.Spec.DNSConfig.Nameservers)).To(BeTrue())
|
||||
Expect(StringInSlice("foobar.com", pod.Spec.DNSConfig.Searches)).To(BeTrue())
|
||||
Expect(len(pod.Spec.DNSConfig.Options)).To(BeNumerically(">", 0))
|
||||
Expect(pod.Spec.DNSConfig.Options[0].Name).To(Equal("color"))
|
||||
Expect(*pod.Spec.DNSConfig.Options[0].Value).To(Equal("blue"))
|
||||
})
|
||||
|
||||
It("podman generate kube multiple contianer dns servers and options are cumulative", func() {
|
||||
top1 := podmanTest.Podman([]string{"run", "-dt", "--name", "top1", "--dns", "8.8.8.8", "--dns-search", "foobar.com", ALPINE, "top"})
|
||||
top1.WaitWithDefaultTimeout()
|
||||
Expect(top1.ExitCode()).To(BeZero())
|
||||
|
||||
top2 := podmanTest.Podman([]string{"run", "-dt", "--name", "top2", "--dns", "8.7.7.7", "--dns-search", "homer.com", ALPINE, "top"})
|
||||
top2.WaitWithDefaultTimeout()
|
||||
Expect(top2.ExitCode()).To(BeZero())
|
||||
|
||||
kube := podmanTest.Podman([]string{"generate", "kube", "top1", "top2"})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube.ExitCode()).To(Equal(0))
|
||||
|
||||
pod := new(v1.Pod)
|
||||
err := yaml.Unmarshal(kube.Out.Contents(), pod)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
Expect(StringInSlice("8.8.8.8", pod.Spec.DNSConfig.Nameservers)).To(BeTrue())
|
||||
Expect(StringInSlice("8.7.7.7", pod.Spec.DNSConfig.Nameservers)).To(BeTrue())
|
||||
Expect(StringInSlice("foobar.com", pod.Spec.DNSConfig.Searches)).To(BeTrue())
|
||||
Expect(StringInSlice("homer.com", pod.Spec.DNSConfig.Searches)).To(BeTrue())
|
||||
})
|
||||
|
||||
It("podman generate kube on a pod with dns options", func() {
|
||||
top := podmanTest.Podman([]string{"run", "--pod", "new:pod1", "-dt", "--name", "top", "--dns", "8.8.8.8", "--dns-search", "foobar.com", "--dns-opt", "color:blue", ALPINE, "top"})
|
||||
top.WaitWithDefaultTimeout()
|
||||
Expect(top.ExitCode()).To(BeZero())
|
||||
|
||||
kube := podmanTest.Podman([]string{"generate", "kube", "pod1"})
|
||||
kube.WaitWithDefaultTimeout()
|
||||
Expect(kube.ExitCode()).To(Equal(0))
|
||||
|
||||
pod := new(v1.Pod)
|
||||
err := yaml.Unmarshal(kube.Out.Contents(), pod)
|
||||
Expect(err).To(BeNil())
|
||||
|
||||
Expect(StringInSlice("8.8.8.8", pod.Spec.DNSConfig.Nameservers)).To(BeTrue())
|
||||
Expect(StringInSlice("foobar.com", pod.Spec.DNSConfig.Searches)).To(BeTrue())
|
||||
Expect(len(pod.Spec.DNSConfig.Options)).To(BeNumerically(">", 0))
|
||||
Expect(pod.Spec.DNSConfig.Options[0].Name).To(Equal("color"))
|
||||
Expect(*pod.Spec.DNSConfig.Options[0].Value).To(Equal("blue"))
|
||||
})
|
||||
})
|
||||
|
Reference in New Issue
Block a user