From a0fb67f2c026a873d6050b6a3db2e1f6c4e7f7fd Mon Sep 17 00:00:00 2001 From: Robbie Zhang Date: Fri, 31 Aug 2018 18:43:34 -0700 Subject: [PATCH] Add validation --- providers/azure/aci.go | 78 +++++++++++++++++++++++++---- providers/azure/client/aci/types.go | 2 +- 2 files changed, 69 insertions(+), 11 deletions(-) diff --git a/providers/azure/aci.go b/providers/azure/aci.go index 182bd9577..f21abd413 100644 --- a/providers/azure/aci.go +++ b/providers/azure/aci.go @@ -47,6 +47,13 @@ const ( networkProfileType = "Microsoft.Network/networkProfiles" ) +// DNS configuration settings +const ( + maxDNSNameservers = 3 + maxDNSSearchPaths = 6 + maxDNSSearchListChars = 256 +) + // ACIProvider implements the virtual-kubelet provider interface and communicates with Azure's ACI APIs. type ACIProvider struct { aciClient *aci.Client @@ -553,10 +560,7 @@ func (p *ACIProvider) amendVnetResources(containerGroup *aci.ContainerGroup, pod containerGroup.NetworkProfile = &aci.NetworkProfileDefinition{ID: p.networkProfile} - extensions := make([]aci.Extension, 0, 1) - extensions = append(extensions, *p.kubeProxyExtension) - - containerGroup.ContainerGroupProperties.Extensions = extensions + containerGroup.ContainerGroupProperties.Extensions = []*aci.Extension{p.kubeProxyExtension} containerGroup.ContainerGroupProperties.DNSConfig = p.getDNSConfig(pod.Spec.DNSPolicy, pod.Spec.DNSConfig) } @@ -567,12 +571,12 @@ func (p *ACIProvider) getDNSConfig(dnsPolicy v1.DNSPolicy, dnsConfig *v1.PodDNSC nameServers = append(nameServers, p.kubeDNSIP) } - var searchDomains string + searchDomains := []string{} options := []string{} if dnsConfig != nil { - nameServers = append(nameServers, dnsConfig.Nameservers...) - searchDomains = strings.Join(dnsConfig.Nameservers, " ") + nameServers = omitDuplicates(append(nameServers, dnsConfig.Nameservers...)) + searchDomains = omitDuplicates(dnsConfig.Searches) for _, option := range dnsConfig.Options { op := option.Name @@ -588,14 +592,68 @@ func (p *ACIProvider) getDNSConfig(dnsPolicy v1.DNSPolicy, dnsConfig *v1.PodDNSC } result := aci.DNSConfig{ - NameServers: nameServers, - SearchDomains: searchDomains, + NameServers: formDNSNameserversFitsLimits(nameServers), + SearchDomains: formDNSSearchFitsLimits(searchDomains), Options: strings.Join(options, " "), } return &result } +func omitDuplicates(strs []string) []string { + uniqueStrs := make(map[string]bool) + + var ret []string + for _, str := range strs { + if !uniqueStrs[str] { + ret = append(ret, str) + uniqueStrs[str] = true + } + } + return ret +} + +func formDNSNameserversFitsLimits(nameservers []string) []string { + if len(nameservers) > maxDNSNameservers { + nameservers = nameservers[:maxDNSNameservers] + msg := fmt.Sprintf("Nameserver limits were exceeded, some nameservers have been omitted, the applied nameserver line is: %s", strings.Join(nameservers, ";")) + log.G(context.TODO()).WithField("method", "formDNSNameserversFitsLimits").Warn(msg) + } + return nameservers +} + +func formDNSSearchFitsLimits(searches []string) string { + limitsExceeded := false + + if len(searches) > maxDNSSearchPaths { + searches = searches[:maxDNSSearchPaths] + limitsExceeded = true + } + + if resolvSearchLineStrLen := len(strings.Join(searches, " ")); resolvSearchLineStrLen > maxDNSSearchListChars { + cutDomainsNum := 0 + cutDomainsLen := 0 + for i := len(searches) - 1; i >= 0; i-- { + cutDomainsLen += len(searches[i]) + 1 + cutDomainsNum++ + + if (resolvSearchLineStrLen - cutDomainsLen) <= maxDNSSearchListChars { + break + } + } + + searches = searches[:(len(searches) - cutDomainsNum)] + limitsExceeded = true + } + + if limitsExceeded { + msg := fmt.Sprintf("Search Line limits were exceeded, some search paths have been omitted, the applied search line is: %s", strings.Join(searches, ";")) + log.G(context.TODO()).WithField("method", "formDNSSearchFitsLimits").Warn(msg) + } + + return strings.Join(searches, " ") +} + func containerGroupName(pod *v1.Pod) string { return fmt.Sprintf("%s-%s", pod.Namespace, pod.Name) } @@ -655,7 +713,7 @@ func (p *ACIProvider) GetContainerLogs(namespace, podName, containerName string, return logContent, err } -// Get full pod name as defined in the provider context +// GetPodFullName as defined in the provider context func (p *ACIProvider) GetPodFullName(namespace string, pod string) string { return fmt.Sprintf("%s-%s", namespace, pod) } diff --git a/providers/azure/client/aci/types.go b/providers/azure/client/aci/types.go index 4c7fa2501..fd152a80c 100644 --- a/providers/azure/client/aci/types.go +++ b/providers/azure/client/aci/types.go @@ -95,7 +95,7 @@ type ContainerGroupProperties struct { InstanceView ContainerGroupPropertiesInstanceView `json:"instanceView,omitempty"` Diagnostics *ContainerGroupDiagnostics `json:"diagnostics,omitempty"` NetworkProfile *NetworkProfileDefinition `json:"networkProfile,omitempty"` - Extensions []Extension `json:"extension,omitempty"` + Extensions []*Extension `json:"extension,omitempty"` DNSConfig *DNSConfig `json:"dnsConfig,omitempty"` }