diff --git a/build/kube-dns/CHANGELOG.md b/build/kube-dns/CHANGELOG.md deleted file mode 100644 index 891bdc26902..00000000000 --- a/build/kube-dns/CHANGELOG.md +++ /dev/null @@ -1,26 +0,0 @@ -### Version 1.9 (Fri November 18 2016 Bowei Du ) -- Add limited ConfigMap support (pr #36775) - -### Version 1.8 (Thu September 29 2016 Zihong Zheng ) -- Add support for graceful termination (issue #31807) - -### Version 1.7 (Wed August 24 2016 Zihong Zheng ) -- Add support for ExternalName services (pr #31159) - -### Version 1.6 (Wed June 29 2016 Girish Kalele ) -- Godeps update for vendor code (skydns/mux) - -### Version 1.5 (Thu June 23 2016 Nikhil Jindal ) -- Adding support to return local service (pr #27708) - -### Version 1.4 (Tue June 21 2016 Nikhil Jindal ) -- Initialising nodesStore (issue #27820) - -### Version 1.3 (Fri June 3 2016 Prashanth.B ) -- Fixed SRV record lookup (issue #26116) - -### Version 1.2 (Fri May 27 2016 Tim Hockin ) -- First Changelog entry - - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/build/kube-dns/CHANGELOG.md?pixel)]() diff --git a/build/kube-dns/Dockerfile b/build/kube-dns/Dockerfile deleted file mode 100644 index 33f43821790..00000000000 --- a/build/kube-dns/Dockerfile +++ /dev/null @@ -1,17 +0,0 @@ -# Copyright 2016 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -FROM BASEIMAGE -ADD kube-dns / -ENTRYPOINT ["/kube-dns"] diff --git a/build/kube-dns/MAINTAINERS.md b/build/kube-dns/MAINTAINERS.md deleted file mode 100644 index 8e16d516637..00000000000 --- a/build/kube-dns/MAINTAINERS.md +++ /dev/null @@ -1,5 +0,0 @@ -# Maintainers - -Tim Hockin - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/build/kube-dns/MAINTAINERS.md?pixel)]() diff --git a/build/kube-dns/Makefile b/build/kube-dns/Makefile deleted file mode 100644 index 1eb1d161912..00000000000 --- a/build/kube-dns/Makefile +++ /dev/null @@ -1,68 +0,0 @@ -# Copyright 2016 The Kubernetes Authors. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# Makefile for the Docker image gcr.io/google_containers/kubedns- -# MAINTAINER: Tim Hockin -# If you update this image please bump the tag value before pushing. -# -# Usage: -# [ARCH=amd64] [TAG=1.6] [REGISTRY=gcr.io/google_containers] [BASEIMAGE=busybox] make (container|push) - -# Default registry, arch and tag. This can be overwritten by arguments to make -PLATFORM?=linux -ARCH?=amd64 -TAG?=1.9 -REGISTRY?=gcr.io/google_containers - -GOLANG_VERSION=1.6 -KUBE_ROOT=$(shell pwd)/../.. -TEMP_DIR:=$(shell mktemp -d) - -ifeq ($(ARCH),amd64) - BASEIMAGE?=busybox -endif -ifeq ($(ARCH),arm) - BASEIMAGE?=armel/busybox -endif -ifeq ($(ARCH),arm64) - BASEIMAGE?=aarch64/busybox -endif -ifeq ($(ARCH),ppc64le) - BASEIMAGE?=ppc64le/busybox -endif -ifeq ($(ARCH),s390x) - BASEIMAGE?=s390x/busybox -endif - - -all: container - -container: - # Copy the content in this dir to the temp dir - cp $(KUBE_ROOT)/_output/dockerized/bin/$(PLATFORM)/$(ARCH)/kube-dns $(TEMP_DIR) - cp $(KUBE_ROOT)/build/kube-dns/Dockerfile $(TEMP_DIR) - - # Replace BASEIMAGE with the real base image - cd $(TEMP_DIR) && sed -i "s|BASEIMAGE|$(BASEIMAGE)|g" Dockerfile - - # And build the image - docker build -t $(REGISTRY)/kubedns-$(ARCH):$(TAG) $(TEMP_DIR) - - # delete temp dir - rm -rf $(TEMP_DIR) - -push: container - gcloud docker -- push $(REGISTRY)/kubedns-$(ARCH):$(TAG) - -.PHONY: all container push diff --git a/build/kube-dns/OWNERS b/build/kube-dns/OWNERS deleted file mode 100644 index c44e663258c..00000000000 --- a/build/kube-dns/OWNERS +++ /dev/null @@ -1,11 +0,0 @@ -approvers: -- thockin -- boweidu -- mrhohn -reviewers: -- mikedanese -- nikhiljindal -- bprashanth -- luxas -- jessfraz -- david-mcmahon diff --git a/build/kube-dns/README.md b/build/kube-dns/README.md deleted file mode 100644 index 63d7e34bcd8..00000000000 --- a/build/kube-dns/README.md +++ /dev/null @@ -1,22 +0,0 @@ -# DNS in Kubernetes - -Kubernetes offers a DNS cluster addon, which most of the supported environments -enable by default. The source code is in [cmd/kube-dns][kube-dns]. - -The [Kubernetes DNS Admin Guide][dns-admin] provides further details on this plugin. - -[kube-dns]: https://github.com/kubernetes/kubernetes/tree/master/cmd/kube-dns -[dns-admin]: http://kubernetes.io/docs/admin/dns/ - -## Making Changes - -The container containing the kube-dns binary needs to be built for every -architecture and pushed to the registry manually whenever the kube-dns binary -has code changes. Every significant change to the functionality should result -in a bump of the TAG in the Makefile. - -Any significant changes to the YAML template for `kube-dns` should result a bump -of the version number for the `kube-dns` replication controller and well as the -`version` label. This will permit a rolling update of `kube-dns`. - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/build/kube-dns/README.md?pixel)]() diff --git a/build/kube-dns/RELEASES.md b/build/kube-dns/RELEASES.md deleted file mode 100644 index 264a2e09d2e..00000000000 --- a/build/kube-dns/RELEASES.md +++ /dev/null @@ -1,51 +0,0 @@ -# Cutting a release - -Until we have a proper setup for building this automatically with every binary -release, here are the steps for making a release. We make releases when they -are ready, not on every PR. - -1. Build the container for testing: - -``` -make release -cd build/kube-dns -make container PREFIX= TAG=rc -``` - -2. Manually deploy this to your own cluster by updating the replication - controller and deleting the running pod(s). - -3. Verify it works. - -4. Update the TAG version in `Makefile` and update the `Changelog`. Update the - `*.yaml.in` to point to the new tag. Send a PR but mark it as "DO NOT MERGE". - -5. Once the PR is approved, build and push the container for real **for all architectures**: - - ```console - # Build for linux/amd64 (default) - $ make push ARCH=amd64 - # ---> gcr.io/google_containers/kube-dns-amd64:TAG - - $ make push ARCH=arm - # ---> gcr.io/google_containers/kube-dns-arm:TAG - - $ make push ARCH=arm64 - # ---> gcr.io/google_containers/kube-dns-arm64:TAG - - $ make push ARCH=ppc64le - # ---> gcr.io/google_containers/kube-dns-ppc64le:TAG - - $ make push ARCH=s390x - # ---> gcr.io/google_containers/kube-dns-s390x:TAG - ``` - -6. Manually deploy this to your own cluster by updating the replication - controller and deleting the running pod(s). - -7. Verify it works. - -8. Allow the PR to be merged. - - -[![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/build/kube-dns/RELEASES.md?pixel)]() diff --git a/cluster/addons/dns/README.md b/cluster/addons/dns/README.md index d82b74300bc..3ac63419d79 100644 --- a/cluster/addons/dns/README.md +++ b/cluster/addons/dns/README.md @@ -1,10 +1,13 @@ # kube-dns -kube-dns schedules DNS Pods and Service on the cluster, other pods in cluster can -use the DNS Service’s IP to resolve DNS names. -More details on http://kubernetes.io/docs/admin/dns/. +`kube-dns` schedules DNS Pods and Service on the cluster, other pods in cluster +can use the DNS Service’s IP to resolve DNS names. + +* [Administrators guide](http://kubernetes.io/docs/admin/dns/) +* [Code repository](http://www.github.com/kubernetes/dns) ## Manually scale kube-dns Deployment + kube-dns creates only one DNS Pod by default. If [dns-horizontal-autoscaler](../dns-horizontal-autoscaler/) is not enabled, you may need to manually scale kube-dns Deployment. @@ -14,27 +17,28 @@ Please use below `kubectl scale` command to scale: kubectl --namespace=kube-system scale deployment kube-dns --replicas= ``` -Do not use `kubectl edit` to modify kube-dns Deployment object if it is controlled by -[Addon Manager](../addon-manager/). Otherwise the modifications will be clobbered, -in addition the replicas count for kube-dns Deployment will be reset to 1. See -[Cluster add-ons README](../README.md) and [#36411](https://github.com/kubernetes/kubernetes/issues/36411) -for reference. +Do not use `kubectl edit` to modify kube-dns Deployment object if it is +controlled by [Addon Manager](../addon-manager/). Otherwise the modifications +will be clobbered, in addition the replicas count for kube-dns Deployment will +be reset to 1. See [Cluster add-ons README](../README.md) and +[#36411](https://github.com/kubernetes/kubernetes/issues/36411) for reference. ## kube-dns Deployment and Service templates -This directory contains the base UNDERSCORE templates that can be used -to generate the kubedns-controller.yaml.in and kubedns.controller.yaml.in needed in Salt format. +This directory contains the base UNDERSCORE templates that can be used to +generate the kubedns-controller.yaml.in and kubedns.controller.yaml.in needed in +Salt format. Due to a varied preference in templating language choices, the transform -Makefile in this directory should be enhanced to generate all required -formats from the base underscore templates. +Makefile in this directory should be enhanced to generate all required formats +from the base underscore templates. + +**N.B.**: When you add a parameter you should also update the various scripts +that supply values for your new parameter. Here is one way you might find those +scripts: -**NOTE WELL**: Developers, when you add a parameter you should also -update the various scripts that supply values for your new parameter. -Here is one way you might find those scripts: ``` -cd kubernetes -find [a-zA-Z0-9]* -type f -exec grep kubedns-controller.yaml \{\} \; -print -exec echo \; +cd kubernetes && git grep 'kubedns-controller.yaml' ``` ### Base Template files @@ -42,17 +46,23 @@ find [a-zA-Z0-9]* -type f -exec grep kubedns-controller.yaml \{\} \; -print -exe These are the authoritative base templates. Run 'make' to generate the Salt and Sed yaml templates from these. +``` kubedns-controller.yaml.base kubedns-svc.yaml.base +``` ### Generated Salt files +``` kubedns-controller.yaml.in kubedns-svc.yaml.in +``` ### Generated Sed files +``` kubedns-controller.yaml.sed kubedns-svc.yaml.sed +``` [![Analytics](https://kubernetes-site.appspot.com/UA-36037335-10/GitHub/cluster/addons/dns/README.md?pixel)]() diff --git a/cluster/addons/dns/kubedns-controller.yaml.base b/cluster/addons/dns/kubedns-controller.yaml.base index 7e788edf889..c613659270b 100644 --- a/cluster/addons/dns/kubedns-controller.yaml.base +++ b/cluster/addons/dns/kubedns-controller.yaml.base @@ -47,7 +47,7 @@ spec: spec: containers: - name: kubedns - image: gcr.io/google_containers/kubedns-amd64:1.9 + image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.10.1 resources: # TODO: Set memory limits when we've profiled the container for large # clusters, then set request = limit to keep this container in @@ -96,7 +96,7 @@ spec: name: metrics protocol: TCP - name: dnsmasq - image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4 + image: gcr.io/google_containers/k8s-dns-dnsmasq-amd64:1.10.1 livenessProbe: httpGet: path: /healthcheck/dnsmasq @@ -124,7 +124,7 @@ spec: cpu: 150m memory: 10Mi - name: sidecar - image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.10.0 + image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.10.1 livenessProbe: httpGet: path: /metrics diff --git a/cluster/addons/dns/kubedns-controller.yaml.in b/cluster/addons/dns/kubedns-controller.yaml.in index b504fe3d0bc..db8528963b4 100644 --- a/cluster/addons/dns/kubedns-controller.yaml.in +++ b/cluster/addons/dns/kubedns-controller.yaml.in @@ -47,7 +47,7 @@ spec: spec: containers: - name: kubedns - image: gcr.io/google_containers/kubedns-amd64:1.9 + image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.10.1 resources: # TODO: Set memory limits when we've profiled the container for large # clusters, then set request = limit to keep this container in @@ -96,7 +96,7 @@ spec: name: metrics protocol: TCP - name: dnsmasq - image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4 + image: gcr.io/google_containers/k8s-dns-dnsmasq-amd64:1.10.1 livenessProbe: httpGet: path: /healthcheck/dnsmasq @@ -124,7 +124,7 @@ spec: cpu: 150m memory: 10Mi - name: sidecar - image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.10.0 + image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.10.1 livenessProbe: httpGet: path: /metrics diff --git a/cluster/addons/dns/kubedns-controller.yaml.sed b/cluster/addons/dns/kubedns-controller.yaml.sed index 7820d2f7fc8..424287bc4ac 100644 --- a/cluster/addons/dns/kubedns-controller.yaml.sed +++ b/cluster/addons/dns/kubedns-controller.yaml.sed @@ -47,7 +47,7 @@ spec: spec: containers: - name: kubedns - image: gcr.io/google_containers/kubedns-amd64:1.9 + image: gcr.io/google_containers/k8s-dns-kube-dns-amd64:1.10.1 resources: # TODO: Set memory limits when we've profiled the container for large # clusters, then set request = limit to keep this container in @@ -95,7 +95,7 @@ spec: name: metrics protocol: TCP - name: dnsmasq - image: gcr.io/google_containers/kube-dnsmasq-amd64:1.4 + image: gcr.io/google_containers/k8s-dns-dnsmasq-amd64:1.10.1 livenessProbe: httpGet: path: /healthcheck/dnsmasq @@ -123,7 +123,7 @@ spec: cpu: 150m memory: 10Mi - name: sidecar - image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.10.0 + image: gcr.io/google_containers/k8s-dns-sidecar-amd64:1.10.1 livenessProbe: httpGet: path: /metrics diff --git a/cmd/BUILD b/cmd/BUILD index 316fe507dcb..6aad0ddece2 100644 --- a/cmd/BUILD +++ b/cmd/BUILD @@ -26,7 +26,6 @@ filegroup( "//cmd/kube-apiserver:all-srcs", "//cmd/kube-controller-manager:all-srcs", "//cmd/kube-discovery:all-srcs", - "//cmd/kube-dns:all-srcs", "//cmd/kube-proxy:all-srcs", "//cmd/kubeadm:all-srcs", "//cmd/kubectl:all-srcs", diff --git a/cmd/kube-dns/BUILD b/cmd/kube-dns/BUILD deleted file mode 100644 index eb54a96f6b3..00000000000 --- a/cmd/kube-dns/BUILD +++ /dev/null @@ -1,49 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_binary", - "go_library", -) - -go_binary( - name = "kube-dns", - library = ":go_default_library", - tags = ["automanaged"], -) - -go_library( - name = "go_default_library", - srcs = ["dns.go"], - tags = ["automanaged"], - deps = [ - "//cmd/kube-dns/app:go_default_library", - "//cmd/kube-dns/app/options:go_default_library", - "//pkg/client/metrics/prometheus:go_default_library", - "//pkg/util/flag:go_default_library", - "//pkg/util/logs:go_default_library", - "//pkg/version:go_default_library", - "//pkg/version/prometheus:go_default_library", - "//pkg/version/verflag:go_default_library", - "//vendor:github.com/golang/glog", - "//vendor:github.com/spf13/pflag", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//cmd/kube-dns/app:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/cmd/kube-dns/app/BUILD b/cmd/kube-dns/app/BUILD deleted file mode 100644 index 0d3b434b904..00000000000 --- a/cmd/kube-dns/app/BUILD +++ /dev/null @@ -1,42 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["server.go"], - tags = ["automanaged"], - deps = [ - "//cmd/kube-dns/app/options:go_default_library", - "//pkg/dns:go_default_library", - "//pkg/dns/config:go_default_library", - "//vendor:github.com/golang/glog", - "//vendor:github.com/skynetservices/skydns/metrics", - "//vendor:github.com/skynetservices/skydns/server", - "//vendor:github.com/spf13/pflag", - "//vendor:k8s.io/client-go/kubernetes", - "//vendor:k8s.io/client-go/rest", - "//vendor:k8s.io/client-go/tools/clientcmd", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//cmd/kube-dns/app/options:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/cmd/kube-dns/app/options/BUILD b/cmd/kube-dns/app/options/BUILD deleted file mode 100644 index 1e4ac03a722..00000000000 --- a/cmd/kube-dns/app/options/BUILD +++ /dev/null @@ -1,33 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["options.go"], - tags = ["automanaged"], - deps = [ - "//pkg/api:go_default_library", - "//pkg/dns/federation:go_default_library", - "//pkg/util/validation:go_default_library", - "//vendor:github.com/spf13/pflag", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/cmd/kube-dns/app/options/options.go b/cmd/kube-dns/app/options/options.go deleted file mode 100644 index 60908dbed21..00000000000 --- a/cmd/kube-dns/app/options/options.go +++ /dev/null @@ -1,168 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package options contains flags for initializing a proxy. -package options - -import ( - "fmt" - _ "net/http/pprof" - "net/url" - "os" - "strings" - "time" - - "github.com/spf13/pflag" - "k8s.io/kubernetes/pkg/api" - fed "k8s.io/kubernetes/pkg/dns/federation" - "k8s.io/kubernetes/pkg/util/validation" -) - -type KubeDNSConfig struct { - ClusterDomain string - KubeConfigFile string - KubeMasterURL string - InitialSyncTimeout time.Duration - - HealthzPort int - DNSBindAddress string - DNSPort int - - Federations map[string]string - - ConfigMapNs string - ConfigMap string -} - -func NewKubeDNSConfig() *KubeDNSConfig { - return &KubeDNSConfig{ - ClusterDomain: "cluster.local.", - HealthzPort: 8081, - DNSBindAddress: "0.0.0.0", - DNSPort: 53, - InitialSyncTimeout: 60 * time.Second, - - Federations: make(map[string]string), - - ConfigMapNs: api.NamespaceSystem, - ConfigMap: "", // default to using command line flags - } -} - -type clusterDomainVar struct { - val *string -} - -func (m clusterDomainVar) Set(v string) error { - v = strings.TrimSuffix(v, ".") - segments := strings.Split(v, ".") - for _, segment := range segments { - if errs := validation.IsDNS1123Label(segment); len(errs) > 0 { - return fmt.Errorf("Not a valid DNS label. %v", errs) - } - } - if !strings.HasSuffix(v, ".") { - v = fmt.Sprintf("%s.", v) - } - *m.val = v - return nil -} - -func (m clusterDomainVar) String() string { - return *m.val -} - -func (m clusterDomainVar) Type() string { - return "string" -} - -type kubeMasterURLVar struct { - val *string -} - -func (m kubeMasterURLVar) Set(v string) error { - parsedURL, err := url.Parse(os.ExpandEnv(v)) - if err != nil { - return fmt.Errorf("failed to parse kube-master-url") - } - if parsedURL.Scheme == "" || parsedURL.Host == "" || parsedURL.Host == ":" { - return fmt.Errorf("invalid kube-master-url specified") - } - *m.val = v - return nil -} - -func (m kubeMasterURLVar) String() string { - return *m.val -} - -func (m kubeMasterURLVar) Type() string { - return "string" -} - -type federationsVar struct { - nameDomainMap map[string]string -} - -func (fv federationsVar) Set(keyVal string) error { - return fed.ParseFederationsFlag(keyVal, fv.nameDomainMap) -} - -func (fv federationsVar) String() string { - var splits []string - for name, domain := range fv.nameDomainMap { - splits = append(splits, fmt.Sprintf("%s=%s", name, domain)) - } - return strings.Join(splits, ",") -} - -func (fv federationsVar) Type() string { - return "[]string" -} - -func (s *KubeDNSConfig) AddFlags(fs *pflag.FlagSet) { - fs.Var(clusterDomainVar{&s.ClusterDomain}, "domain", - "domain under which to create names") - - fs.StringVar(&s.KubeConfigFile, "kubecfg-file", s.KubeConfigFile, - "Location of kubecfg file for access to kubernetes master service;"+ - " --kube-master-url overrides the URL part of this; if neither this nor"+ - " --kube-master-url are provided, defaults to service account tokens") - fs.Var(kubeMasterURLVar{&s.KubeMasterURL}, "kube-master-url", - "URL to reach kubernetes master. Env variables in this flag will be expanded.") - - fs.IntVar(&s.HealthzPort, "healthz-port", s.HealthzPort, - "port on which to serve a kube-dns HTTP readiness probe.") - fs.StringVar(&s.DNSBindAddress, "dns-bind-address", s.DNSBindAddress, - "address on which to serve DNS requests.") - fs.IntVar(&s.DNSPort, "dns-port", s.DNSPort, "port on which to serve DNS requests.") - - fs.Var(federationsVar{s.Federations}, "federations", - "a comma separated list of the federation names and their corresponding"+ - " domain names to which this cluster belongs. Example:"+ - " \"myfederation1=example.com,myfederation2=example2.com,myfederation3=example.com\"."+ - " It is an error to set both the federations and config-map flags.") - fs.MarkDeprecated("federations", "use config-map instead. Will be removed in future version") - - fs.StringVar(&s.ConfigMapNs, "config-map-namespace", s.ConfigMapNs, - "namespace for the config-map") - fs.StringVar(&s.ConfigMap, "config-map", s.ConfigMap, - "config-map name. If empty, then the config-map will not used. Cannot be "+ - " used in conjunction with federations flag. config-map contains "+ - "dynamically adjustable configuration.") - fs.DurationVar(&s.InitialSyncTimeout, "initial-sync-timeout", s.InitialSyncTimeout, - "Timeout for initial resource sync.") -} diff --git a/cmd/kube-dns/app/server.go b/cmd/kube-dns/app/server.go deleted file mode 100644 index be6ba3453fd..00000000000 --- a/cmd/kube-dns/app/server.go +++ /dev/null @@ -1,156 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package app - -import ( - "fmt" - "net/http" - "os" - "os/signal" - "syscall" - - "github.com/golang/glog" - "github.com/skynetservices/skydns/metrics" - "github.com/skynetservices/skydns/server" - "github.com/spf13/pflag" - - "k8s.io/kubernetes/cmd/kube-dns/app/options" - "k8s.io/kubernetes/pkg/dns" - dnsconfig "k8s.io/kubernetes/pkg/dns/config" - - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/rest" - "k8s.io/client-go/tools/clientcmd" -) - -type KubeDNSServer struct { - // DNS domain name. - domain string - healthzPort int - dnsBindAddress string - dnsPort int - kd *dns.KubeDNS -} - -func NewKubeDNSServerDefault(config *options.KubeDNSConfig) *KubeDNSServer { - kubeClient, err := newKubeClient(config) - if err != nil { - glog.Fatalf("Failed to create a kubernetes client: %v", err) - } - - var configSync dnsconfig.Sync - if config.ConfigMap == "" { - glog.V(0).Infof("ConfigMap not configured, using values from command line flags") - configSync = dnsconfig.NewNopSync( - &dnsconfig.Config{Federations: config.Federations}) - } else { - glog.V(0).Infof("Using configuration read from ConfigMap: %v:%v", - config.ConfigMapNs, config.ConfigMap) - configSync = dnsconfig.NewSync( - kubeClient, config.ConfigMapNs, config.ConfigMap) - } - - return &KubeDNSServer{ - domain: config.ClusterDomain, - healthzPort: config.HealthzPort, - dnsBindAddress: config.DNSBindAddress, - dnsPort: config.DNSPort, - kd: dns.NewKubeDNS(kubeClient, config.ClusterDomain, config.InitialSyncTimeout, configSync), - } -} - -func newKubeClient(dnsConfig *options.KubeDNSConfig) (kubernetes.Interface, error) { - var config *rest.Config - var err error - - if dnsConfig.KubeConfigFile == "" { - config, err = rest.InClusterConfig() - if err != nil { - return nil, err - } - } else { - config, err = clientcmd.BuildConfigFromFlags( - dnsConfig.KubeMasterURL, dnsConfig.KubeConfigFile) - if err != nil { - return nil, err - } - } - - return kubernetes.NewForConfig(config) -} - -func (server *KubeDNSServer) Run() { - pflag.VisitAll(func(flag *pflag.Flag) { - glog.V(0).Infof("FLAG: --%s=%q", flag.Name, flag.Value) - }) - setupSignalHandlers() - server.startSkyDNSServer() - server.kd.Start() - server.setupHandlers() - - glog.V(0).Infof("Status HTTP port %v", server.healthzPort) - glog.Fatal(http.ListenAndServe(fmt.Sprintf(":%d", server.healthzPort), nil)) -} - -// setupHealthzHandlers sets up a readiness and liveness endpoint for kube2sky. -func (server *KubeDNSServer) setupHandlers() { - glog.V(0).Infof("Setting up Healthz Handler (/readiness)") - http.HandleFunc("/readiness", func(w http.ResponseWriter, req *http.Request) { - fmt.Fprintf(w, "ok\n") - }) - - glog.V(0).Infof("Setting up cache handler (/cache)") - http.HandleFunc("/cache", func(w http.ResponseWriter, req *http.Request) { - serializedJSON, err := server.kd.GetCacheAsJSON() - if err == nil { - fmt.Fprint(w, serializedJSON) - } else { - w.WriteHeader(http.StatusInternalServerError) - fmt.Fprint(w, err) - } - }) -} - -// setupSignalHandlers installs signal handler to ignore SIGINT and -// SIGTERM. This daemon will be killed by SIGKILL after the grace -// period to allow for some manner of graceful shutdown. -func setupSignalHandlers() { - sigChan := make(chan os.Signal) - signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM) - go func() { - glog.V(0).Infof("Ignoring signal %v (can only be terminated by SIGKILL)", <-sigChan) - }() -} - -func (d *KubeDNSServer) startSkyDNSServer() { - glog.V(0).Infof("Starting SkyDNS server (%v:%v)", d.dnsBindAddress, d.dnsPort) - skydnsConfig := &server.Config{ - Domain: d.domain, - DnsAddr: fmt.Sprintf("%s:%d", d.dnsBindAddress, d.dnsPort), - } - server.SetDefaults(skydnsConfig) - s := server.New(d.kd, skydnsConfig) - if err := metrics.Metrics(); err != nil { - glog.Fatalf("Skydns metrics error: %s", err) - } else if metrics.Port != "" { - glog.V(0).Infof("Skydns metrics enabled (%v:%v)", metrics.Path, metrics.Port) - } else { - glog.V(0).Infof("Skydns metrics not enabled") - } - - go s.Run() -} diff --git a/cmd/kube-dns/dns.go b/cmd/kube-dns/dns.go deleted file mode 100644 index 273ca822d8a..00000000000 --- a/cmd/kube-dns/dns.go +++ /dev/null @@ -1,48 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package main - -import ( - "github.com/golang/glog" - "github.com/spf13/pflag" - - "k8s.io/kubernetes/cmd/kube-dns/app" - "k8s.io/kubernetes/cmd/kube-dns/app/options" - "k8s.io/kubernetes/pkg/util/flag" - "k8s.io/kubernetes/pkg/util/logs" - "k8s.io/kubernetes/pkg/version" - "k8s.io/kubernetes/pkg/version/verflag" - - _ "k8s.io/kubernetes/pkg/client/metrics/prometheus" // for client metric registration - _ "k8s.io/kubernetes/pkg/version/prometheus" // for version metric registration -) - -func main() { - config := options.NewKubeDNSConfig() - config.AddFlags(pflag.CommandLine) - - flag.InitFlags() - logs.InitLogs() - defer logs.FlushLogs() - - verflag.PrintAndExitIfRequested() - - glog.V(0).Infof("version: %+v", version.Get()) - - server := app.NewKubeDNSServerDefault(config) - server.Run() -} diff --git a/hack/.linted_packages b/hack/.linted_packages index 4c9b9ec41ab..dd511372ddd 100644 --- a/hack/.linted_packages +++ b/hack/.linted_packages @@ -15,7 +15,6 @@ cmd/kube-apiserver/app/options cmd/kube-controller-manager cmd/kube-controller-manager/app/options cmd/kube-discovery -cmd/kube-dns cmd/kube-proxy cmd/kubeadm cmd/kubeadm diff --git a/hack/lib/golang.sh b/hack/lib/golang.sh index e5af3fb80ed..0c695100144 100755 --- a/hack/lib/golang.sh +++ b/hack/lib/golang.sh @@ -23,7 +23,6 @@ readonly KUBE_GOPATH="${KUBE_OUTPUT}/go" # kube::build::source_targets in build/common.sh as well. kube::golang::server_targets() { local targets=( - cmd/kube-dns cmd/kube-proxy cmd/kube-apiserver cmd/kube-controller-manager @@ -189,7 +188,6 @@ readonly KUBE_ALL_BINARIES=("${KUBE_ALL_TARGETS[@]##*/}") readonly KUBE_STATIC_LIBRARIES=( kube-apiserver kube-controller-manager - kube-dns kube-scheduler kube-proxy kube-discovery diff --git a/pkg/BUILD b/pkg/BUILD index a56f72a3878..ee6fc72c2a7 100644 --- a/pkg/BUILD +++ b/pkg/BUILD @@ -85,7 +85,6 @@ filegroup( "//pkg/controller:all-srcs", "//pkg/conversion:all-srcs", "//pkg/credentialprovider:all-srcs", - "//pkg/dns:all-srcs", "//pkg/fieldpath:all-srcs", "//pkg/fields:all-srcs", "//pkg/generated:all-srcs", diff --git a/pkg/dns/BUILD b/pkg/dns/BUILD deleted file mode 100644 index d35aa89ebb4..00000000000 --- a/pkg/dns/BUILD +++ /dev/null @@ -1,77 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "dns.go", - "doc.go", - ], - tags = ["automanaged"], - deps = [ - "//pkg/dns/config:go_default_library", - "//pkg/dns/treecache:go_default_library", - "//pkg/dns/util:go_default_library", - "//pkg/util/validation:go_default_library", - "//pkg/util/wait:go_default_library", - "//vendor:github.com/coreos/etcd/client", - "//vendor:github.com/golang/glog", - "//vendor:github.com/miekg/dns", - "//vendor:github.com/skynetservices/skydns/msg", - "//vendor:k8s.io/client-go/kubernetes", - "//vendor:k8s.io/client-go/pkg/api/v1", - "//vendor:k8s.io/client-go/pkg/apis/meta/v1", - "//vendor:k8s.io/client-go/pkg/runtime", - "//vendor:k8s.io/client-go/pkg/watch", - "//vendor:k8s.io/client-go/tools/cache", - ], -) - -go_test( - name = "go_default_test", - srcs = ["dns_test.go"], - library = ":go_default_library", - tags = ["automanaged"], - deps = [ - "//pkg/dns/config:go_default_library", - "//pkg/dns/treecache:go_default_library", - "//pkg/dns/util:go_default_library", - "//pkg/util/sets:go_default_library", - "//vendor:github.com/coreos/etcd/client", - "//vendor:github.com/miekg/dns", - "//vendor:github.com/skynetservices/skydns/msg", - "//vendor:github.com/skynetservices/skydns/server", - "//vendor:github.com/stretchr/testify/assert", - "//vendor:github.com/stretchr/testify/require", - "//vendor:k8s.io/client-go/kubernetes/fake", - "//vendor:k8s.io/client-go/pkg/api/v1", - "//vendor:k8s.io/client-go/pkg/apis/meta/v1", - "//vendor:k8s.io/client-go/tools/cache", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [ - ":package-srcs", - "//pkg/dns/config:all-srcs", - "//pkg/dns/federation:all-srcs", - "//pkg/dns/treecache:all-srcs", - "//pkg/dns/util:all-srcs", - ], - tags = ["automanaged"], -) diff --git a/pkg/dns/config/BUILD b/pkg/dns/config/BUILD deleted file mode 100644 index cd99953025a..00000000000 --- a/pkg/dns/config/BUILD +++ /dev/null @@ -1,53 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = [ - "config.go", - "mocksync.go", - "nopsync.go", - "sync.go", - ], - tags = ["automanaged"], - deps = [ - "//pkg/dns/federation:go_default_library", - "//vendor:github.com/golang/glog", - "//vendor:k8s.io/client-go/kubernetes", - "//vendor:k8s.io/client-go/pkg/api/v1", - "//vendor:k8s.io/client-go/pkg/apis/meta/v1", - "//vendor:k8s.io/client-go/pkg/fields", - "//vendor:k8s.io/client-go/pkg/runtime", - "//vendor:k8s.io/client-go/pkg/util/wait", - "//vendor:k8s.io/client-go/pkg/watch", - "//vendor:k8s.io/client-go/tools/cache", - ], -) - -go_test( - name = "go_default_test", - srcs = ["config_test.go"], - library = ":go_default_library", - tags = ["automanaged"], - deps = ["//vendor:github.com/stretchr/testify/assert"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/dns/config/config.go b/pkg/dns/config/config.go deleted file mode 100644 index 79256cdbed9..00000000000 --- a/pkg/dns/config/config.go +++ /dev/null @@ -1,65 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package config - -import ( - types "k8s.io/client-go/pkg/apis/meta/v1" - fed "k8s.io/kubernetes/pkg/dns/federation" -) - -// Config populated either from the configuration source (command -// line flags or via the config map mechanism). -type Config struct { - // The inclusion of TypeMeta is to ensure future compatibility if the - // Config object was populated directly via a Kubernetes API mechanism. - // - // For example, instead of the custom implementation here, the - // configuration could be obtained from an API that unifies - // command-line flags, config-map, etc mechanisms. - types.TypeMeta - - // Map of federation names that the cluster in which this kube-dns - // is running belongs to, to the corresponding domain names. - Federations map[string]string `json:"federations"` -} - -func NewDefaultConfig() *Config { - return &Config{ - Federations: make(map[string]string), - } -} - -// IsValid returns whether or not the configuration is valid. -func (config *Config) Validate() error { - if err := config.validateFederations(); err != nil { - return err - } - - return nil -} - -func (config *Config) validateFederations() error { - for name, domain := range config.Federations { - if err := fed.ValidateName(name); err != nil { - return err - } - if err := fed.ValidateDomain(domain); err != nil { - return err - } - } - return nil -} diff --git a/pkg/dns/config/config_test.go b/pkg/dns/config/config_test.go deleted file mode 100644 index 45a5753b66c..00000000000 --- a/pkg/dns/config/config_test.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package config - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestValidate(t *testing.T) { - for _, testCase := range []struct { - config *Config - hasError bool - }{ - { - config: &Config{Federations: map[string]string{}}, - }, - { - config: &Config{ - Federations: map[string]string{ - "abc": "d.e.f", - }, - }, - }, - { - config: &Config{ - Federations: map[string]string{ - "a.b": "cdef", - }, - }, - hasError: true, - }, - } { - err := testCase.config.Validate() - if !testCase.hasError { - assert.Nil(t, err, "should be valid", testCase) - } else { - assert.NotNil(t, err, "should not be valid", testCase) - } - } -} diff --git a/pkg/dns/config/mocksync.go b/pkg/dns/config/mocksync.go deleted file mode 100644 index e42f4f1292d..00000000000 --- a/pkg/dns/config/mocksync.go +++ /dev/null @@ -1,46 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package config - -// MockSync is a testing mock. -type MockSync struct { - // Config that will be returned from Once(). - Config *Config - // Error that will be returned from Once(). - Error error - - // Chan to send new configurations on. - Chan chan *Config -} - -var _ Sync = (*MockSync)(nil) - -func NewMockSync(config *Config, error error) *MockSync { - return &MockSync{ - Config: config, - Error: error, - Chan: make(chan *Config), - } -} - -func (sync *MockSync) Once() (*Config, error) { - return sync.Config, sync.Error -} - -func (sync *MockSync) Periodic() <-chan *Config { - return sync.Chan -} diff --git a/pkg/dns/config/nopsync.go b/pkg/dns/config/nopsync.go deleted file mode 100644 index 4225a3ffd3a..00000000000 --- a/pkg/dns/config/nopsync.go +++ /dev/null @@ -1,37 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package config - -// nopSync does no synchronization, used when the DNS server is -// started without a ConfigMap configured. -type nopSync struct { - config *Config -} - -var _ Sync = (*nopSync)(nil) - -func NewNopSync(config *Config) Sync { - return &nopSync{config: config} -} - -func (sync *nopSync) Once() (*Config, error) { - return sync.config, nil -} - -func (sync *nopSync) Periodic() <-chan *Config { - return make(chan *Config) -} diff --git a/pkg/dns/config/sync.go b/pkg/dns/config/sync.go deleted file mode 100644 index 249225f63a6..00000000000 --- a/pkg/dns/config/sync.go +++ /dev/null @@ -1,203 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package config - -import ( - "k8s.io/client-go/kubernetes" - "k8s.io/client-go/pkg/api/v1" - metav1 "k8s.io/client-go/pkg/apis/meta/v1" - "k8s.io/client-go/pkg/fields" - "k8s.io/client-go/pkg/runtime" - "k8s.io/client-go/pkg/util/wait" - "k8s.io/client-go/pkg/watch" - "k8s.io/client-go/tools/cache" - - fed "k8s.io/kubernetes/pkg/dns/federation" - - "time" - - "github.com/golang/glog" -) - -// Sync manages synchronization of the config map. -type Sync interface { - // Once does a blocking synchronization of the config map. If the - // ConfigMap fails to validate, this method will return nil, err. - Once() (*Config, error) - - // Start a periodic synchronization of the configuration map. When a - // successful configuration map update is detected, the - // configuration will be sent to the channel. - // - // It is an error to call this more than once. - Periodic() <-chan *Config -} - -// NewSync for ConfigMap from namespace `ns` and `name`. -func NewSync(client kubernetes.Interface, ns string, name string) Sync { - sync := &kubeSync{ - ns: ns, - name: name, - client: client, - channel: make(chan *Config), - } - - listWatch := &cache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - options.FieldSelector = fields.Set{"metadata.name": name}.AsSelector().String() - return client.Core().ConfigMaps(ns).List(options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - options.FieldSelector = fields.Set{"metadata.name": name}.AsSelector().String() - return client.Core().ConfigMaps(ns).Watch(options) - }, - } - - store, controller := cache.NewInformer( - listWatch, - &v1.ConfigMap{}, - time.Duration(0), - cache.ResourceEventHandlerFuncs{ - AddFunc: sync.onAdd, - DeleteFunc: sync.onDelete, - UpdateFunc: sync.onUpdate, - }) - - sync.store = store - sync.controller = controller - - return sync -} - -// kubeSync implements Sync for the Kubernetes API. -type kubeSync struct { - ns string - name string - - client kubernetes.Interface - store cache.Store - controller *cache.Controller - - channel chan *Config - - latestVersion string -} - -var _ Sync = (*kubeSync)(nil) - -func (sync *kubeSync) Once() (*Config, error) { - cm, err := sync.client.Core().ConfigMaps(sync.ns).Get(sync.name, metav1.GetOptions{}) - - if err != nil { - glog.Errorf("Error getting ConfigMap %v:%v err: %v", - sync.ns, sync.name, err) - return nil, err - } - - config, _, err := sync.processUpdate(cm) - return config, err -} - -func (sync *kubeSync) Periodic() <-chan *Config { - go sync.controller.Run(wait.NeverStop) - return sync.channel -} - -func (sync *kubeSync) toConfigMap(obj interface{}) *v1.ConfigMap { - cm, ok := obj.(*v1.ConfigMap) - if !ok { - glog.Fatalf("Expected ConfigMap, got %T", obj) - } - return cm -} - -func (sync *kubeSync) onAdd(obj interface{}) { - cm := sync.toConfigMap(obj) - - glog.V(2).Infof("ConfigMap %s:%s was created", sync.ns, sync.name) - - config, updated, err := sync.processUpdate(cm) - if updated && err == nil { - sync.channel <- config - } -} - -func (sync *kubeSync) onDelete(_ interface{}) { - glog.V(2).Infof("ConfigMap %s:%s was deleted, reverting to default configuration", - sync.ns, sync.name) - - sync.latestVersion = "" - sync.channel <- NewDefaultConfig() -} - -func (sync *kubeSync) onUpdate(_, obj interface{}) { - cm := sync.toConfigMap(obj) - - glog.V(2).Infof("ConfigMap %s:%s was updated", sync.ns, sync.name) - - config, changed, err := sync.processUpdate(cm) - - if changed && err == nil { - sync.channel <- config - } -} - -func (sync *kubeSync) processUpdate(cm *v1.ConfigMap) (config *Config, changed bool, err error) { - glog.V(4).Infof("processUpdate ConfigMap %+v", *cm) - - if cm.ObjectMeta.ResourceVersion != sync.latestVersion { - glog.V(3).Infof("Updating config to version %v (was %v)", - cm.ObjectMeta.ResourceVersion, sync.latestVersion) - changed = true - sync.latestVersion = cm.ObjectMeta.ResourceVersion - } else { - glog.V(4).Infof("Config was unchanged (version %v)", sync.latestVersion) - return - } - - config = &Config{} - - if err = sync.updateFederations(cm, config); err != nil { - glog.Errorf("Invalid configuration, ignoring update") - return - } - - if err = config.Validate(); err != nil { - glog.Errorf("Invalid onfiguration: %v (value was %+v), ignoring update", - err, config) - config = nil - return - } - - return -} - -func (sync *kubeSync) updateFederations(cm *v1.ConfigMap, config *Config) (err error) { - if flagValue, ok := cm.Data["federations"]; ok { - config.Federations = make(map[string]string) - if err = fed.ParseFederationsFlag(flagValue, config.Federations); err != nil { - glog.Errorf("Invalid federations value: %v (value was %q)", - err, cm.Data["federations"]) - return - } - glog.V(2).Infof("Updated federations to %v", config.Federations) - } else { - glog.V(2).Infof("No federations present") - } - - return -} diff --git a/pkg/dns/dns.go b/pkg/dns/dns.go deleted file mode 100644 index 250c9ba388d..00000000000 --- a/pkg/dns/dns.go +++ /dev/null @@ -1,868 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dns - -import ( - "fmt" - "net" - "strings" - "sync" - "time" - - clientset "k8s.io/client-go/kubernetes" - "k8s.io/client-go/pkg/api/v1" - metav1 "k8s.io/client-go/pkg/apis/meta/v1" - "k8s.io/client-go/pkg/runtime" - "k8s.io/client-go/pkg/watch" - kcache "k8s.io/client-go/tools/cache" - - "k8s.io/kubernetes/pkg/dns/config" - "k8s.io/kubernetes/pkg/dns/treecache" - "k8s.io/kubernetes/pkg/dns/util" - "k8s.io/kubernetes/pkg/util/validation" - "k8s.io/kubernetes/pkg/util/wait" - - etcd "github.com/coreos/etcd/client" - "github.com/golang/glog" - "github.com/miekg/dns" - skymsg "github.com/skynetservices/skydns/msg" -) - -const ( - // A subdomain added to the user specified domain for all services. - serviceSubdomain = "svc" - - // A subdomain added to the user specified dmoain for all pods. - podSubdomain = "pod" - - // Resync period for the kube controller loop. - resyncPeriod = 5 * time.Minute - - // Duration for which the TTL cache should hold the node resource to retrieve the zone - // annotation from it so that it could be added to federation CNAMEs. There is ideally - // no need to expire this cache, but we don't want to assume that node annotations - // never change. So we expire the cache and retrieve a node once every 180 seconds. - // The value is chosen to be neither too long nor too short. - nodeCacheTTL = 180 * time.Second -) - -type KubeDNS struct { - // kubeClient makes calls to API Server and registers calls with API Server - // to get Endpoints and Service objects. - kubeClient clientset.Interface - - // domain for which this DNS Server is authoritative. - domain string - // configMap where kube-dns dynamic configuration is store. If this - // is empty then getting configuration from a configMap will be - // disabled. - configMap string - - // endpointsStore that contains all the endpoints in the system. - endpointsStore kcache.Store - // servicesStore that contains all the services in the system. - servicesStore kcache.Store - // nodesStore contains some subset of nodes in the system so that we - // can retrieve the cluster zone annotation from the cached node - // instead of getting it from the API server every time. - nodesStore kcache.Store - - // cache stores DNS records for the domain. A Records and SRV Records for - // (regular) services and headless Services. CNAME Records for - // ExternalName Services. - cache treecache.TreeCache - // TODO(nikhiljindal): Remove this. It can be recreated using - // clusterIPServiceMap. - reverseRecordMap map[string]*skymsg.Service - // clusterIPServiceMap to service object. Headless services are not - // part of this map. Used to get a service when given its cluster - // IP. Access to this is coordinated using cacheLock. We use the - // same lock for cache and this map to ensure that they don't get - // out of sync. - clusterIPServiceMap map[string]*v1.Service - // cacheLock protecting the cache. caller is responsible for using - // the cacheLock before invoking methods on cache the cache is not - // thread-safe, and the caller can guarantee thread safety by using - // the cacheLock - cacheLock sync.RWMutex - - // The domain for which this DNS Server is authoritative, in array - // format and reversed. e.g. if domain is "cluster.local", - // domainPath is []string{"local", "cluster"} - domainPath []string - - // endpointsController invokes registered callbacks when endpoints change. - endpointsController *kcache.Controller - // serviceController invokes registered callbacks when services change. - serviceController *kcache.Controller - - // config set from the dynamic configuration source. - config *config.Config - // configLock protects the config below. - configLock sync.RWMutex - // configSync manages synchronization of the config map - configSync config.Sync - - // Initial timeout for endpoints and services to be synced from APIServer - initialSyncTimeout time.Duration -} - -func NewKubeDNS(client clientset.Interface, clusterDomain string, timeout time.Duration, configSync config.Sync) *KubeDNS { - kd := &KubeDNS{ - kubeClient: client, - domain: clusterDomain, - cache: treecache.NewTreeCache(), - cacheLock: sync.RWMutex{}, - nodesStore: kcache.NewStore(kcache.MetaNamespaceKeyFunc), - reverseRecordMap: make(map[string]*skymsg.Service), - clusterIPServiceMap: make(map[string]*v1.Service), - domainPath: util.ReverseArray(strings.Split(strings.TrimRight(clusterDomain, "."), ".")), - initialSyncTimeout: timeout, - - configLock: sync.RWMutex{}, - configSync: configSync, - } - - kd.setEndpointsStore() - kd.setServicesStore() - - return kd -} - -func (kd *KubeDNS) Start() { - glog.V(2).Infof("Starting endpointsController") - go kd.endpointsController.Run(wait.NeverStop) - - glog.V(2).Infof("Starting serviceController") - go kd.serviceController.Run(wait.NeverStop) - - kd.startConfigMapSync() - - // Wait synchronously for the initial list operations to be - // complete of endpoints and services from APIServer. - kd.waitForResourceSyncedOrDie() -} - -func (kd *KubeDNS) waitForResourceSyncedOrDie() { - // Wait for both controllers have completed an initial resource listing - timeout := time.After(kd.initialSyncTimeout) - ticker := time.NewTicker(500 * time.Millisecond) - defer ticker.Stop() - for { - select { - case <-timeout: - glog.Fatalf("Timeout waiting for initialization") - case <-ticker.C: - if kd.endpointsController.HasSynced() && kd.serviceController.HasSynced() { - glog.V(0).Infof("Initialized services and endpoints from apiserver") - return - } - glog.V(0).Infof("DNS server not ready, retry in 500 milliseconds") - } - } -} - -func (kd *KubeDNS) startConfigMapSync() { - initialConfig, err := kd.configSync.Once() - if err != nil { - glog.Errorf( - "Error getting initial ConfigMap: %v, starting with default values", err) - kd.config = config.NewDefaultConfig() - } else { - kd.config = initialConfig - } - - go kd.syncConfigMap(kd.configSync.Periodic()) -} - -func (kd *KubeDNS) syncConfigMap(syncChan <-chan *config.Config) { - for { - nextConfig := <-syncChan - - kd.configLock.Lock() - kd.config = nextConfig - glog.V(2).Infof("Configuration updated: %+v", *kd.config) - kd.configLock.Unlock() - } -} - -func (kd *KubeDNS) GetCacheAsJSON() (string, error) { - kd.cacheLock.RLock() - defer kd.cacheLock.RUnlock() - json, err := kd.cache.Serialize() - return json, err -} - -func (kd *KubeDNS) setServicesStore() { - // Returns a cache.ListWatch that gets all changes to services. - kd.servicesStore, kd.serviceController = kcache.NewInformer( - &kcache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - return kd.kubeClient.Core().Services(v1.NamespaceAll).List(options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - return kd.kubeClient.Core().Services(v1.NamespaceAll).Watch(options) - }, - }, - &v1.Service{}, - resyncPeriod, - kcache.ResourceEventHandlerFuncs{ - AddFunc: kd.newService, - DeleteFunc: kd.removeService, - UpdateFunc: kd.updateService, - }, - ) -} - -func (kd *KubeDNS) setEndpointsStore() { - // Returns a cache.ListWatch that gets all changes to endpoints. - kd.endpointsStore, kd.endpointsController = kcache.NewInformer( - &kcache.ListWatch{ - ListFunc: func(options v1.ListOptions) (runtime.Object, error) { - return kd.kubeClient.Core().Endpoints(v1.NamespaceAll).List(options) - }, - WatchFunc: func(options v1.ListOptions) (watch.Interface, error) { - return kd.kubeClient.Core().Endpoints(v1.NamespaceAll).Watch(options) - }, - }, - &v1.Endpoints{}, - resyncPeriod, - kcache.ResourceEventHandlerFuncs{ - AddFunc: kd.handleEndpointAdd, - UpdateFunc: func(oldObj, newObj interface{}) { - // TODO: Avoid unwanted updates. - kd.handleEndpointAdd(newObj) - }, - // No DeleteFunc for EndpointsStore because endpoint object will be deleted - // when corresponding service is deleted. - }, - ) -} - -func assertIsService(obj interface{}) (*v1.Service, bool) { - if service, ok := obj.(*v1.Service); ok { - return service, ok - } else { - glog.Errorf("Type assertion failed! Expected 'Service', got %T", service) - return nil, ok - } -} - -func (kd *KubeDNS) newService(obj interface{}) { - if service, ok := assertIsService(obj); ok { - glog.V(2).Infof("New service: %v", service.Name) - glog.V(4).Infof("Service details: %v", service) - - // ExternalName services are a special kind that return CNAME records - if service.Spec.Type == v1.ServiceTypeExternalName { - kd.newExternalNameService(service) - return - } - // if ClusterIP is not set, a DNS entry should not be created - if !v1.IsServiceIPSet(service) { - kd.newHeadlessService(service) - return - } - if len(service.Spec.Ports) == 0 { - glog.Warningf("Service with no ports, this should not have happened: %v", - service) - } - kd.newPortalService(service) - } -} - -func (kd *KubeDNS) removeService(obj interface{}) { - if s, ok := assertIsService(obj); ok { - subCachePath := append(kd.domainPath, serviceSubdomain, s.Namespace, s.Name) - kd.cacheLock.Lock() - defer kd.cacheLock.Unlock() - - success := kd.cache.DeletePath(subCachePath...) - glog.V(2).Infof("removeService %v at path %v. Success: %v", - s.Name, subCachePath, success) - - // ExternalName services have no IP - if v1.IsServiceIPSet(s) { - delete(kd.reverseRecordMap, s.Spec.ClusterIP) - delete(kd.clusterIPServiceMap, s.Spec.ClusterIP) - } - } -} - -func (kd *KubeDNS) updateService(oldObj, newObj interface{}) { - if new, ok := assertIsService(newObj); ok { - if old, ok := assertIsService(oldObj); ok { - // Remove old cache path only if changing type to/from ExternalName. - // In all other cases, we'll update records in place. - if (new.Spec.Type == v1.ServiceTypeExternalName) != - (old.Spec.Type == v1.ServiceTypeExternalName) { - kd.removeService(oldObj) - } - kd.newService(newObj) - } - } -} - -func (kd *KubeDNS) handleEndpointAdd(obj interface{}) { - if e, ok := obj.(*v1.Endpoints); ok { - kd.addDNSUsingEndpoints(e) - } -} - -func (kd *KubeDNS) addDNSUsingEndpoints(e *v1.Endpoints) error { - svc, err := kd.getServiceFromEndpoints(e) - if err != nil { - return err - } - if svc == nil || v1.IsServiceIPSet(svc) { - // No headless service found corresponding to endpoints object. - return nil - } - return kd.generateRecordsForHeadlessService(e, svc) -} - -func (kd *KubeDNS) getServiceFromEndpoints(e *v1.Endpoints) (*v1.Service, error) { - key, err := kcache.MetaNamespaceKeyFunc(e) - if err != nil { - return nil, err - } - obj, exists, err := kd.servicesStore.GetByKey(key) - if err != nil { - return nil, fmt.Errorf("failed to get service object from services store - %v", err) - } - if !exists { - glog.V(3).Infof("No service for endpoint %q in namespace %q", - e.Name, e.Namespace) - return nil, nil - } - if svc, ok := assertIsService(obj); ok { - return svc, nil - } - return nil, fmt.Errorf("got a non service object in services store %v", obj) -} - -// fqdn constructs the fqdn for the given service. subpaths is a list of path -// elements rooted at the given service, ending at a service record. -func (kd *KubeDNS) fqdn(service *v1.Service, subpaths ...string) string { - domainLabels := append(append(kd.domainPath, serviceSubdomain, service.Namespace, service.Name), subpaths...) - return dns.Fqdn(strings.Join(util.ReverseArray(domainLabels), ".")) -} - -func (kd *KubeDNS) newPortalService(service *v1.Service) { - subCache := treecache.NewTreeCache() - recordValue, recordLabel := util.GetSkyMsg(service.Spec.ClusterIP, 0) - subCache.SetEntry(recordLabel, recordValue, kd.fqdn(service, recordLabel)) - - // Generate SRV Records - for i := range service.Spec.Ports { - port := &service.Spec.Ports[i] - if port.Name != "" && port.Protocol != "" { - srvValue := kd.generateSRVRecordValue(service, int(port.Port)) - - l := []string{"_" + strings.ToLower(string(port.Protocol)), "_" + port.Name} - glog.V(2).Infof("Added SRV record %+v", srvValue) - - subCache.SetEntry(recordLabel, srvValue, kd.fqdn(service, append(l, recordLabel)...), l...) - } - } - subCachePath := append(kd.domainPath, serviceSubdomain, service.Namespace) - host := getServiceFQDN(kd.domain, service) - reverseRecord, _ := util.GetSkyMsg(host, 0) - - kd.cacheLock.Lock() - defer kd.cacheLock.Unlock() - kd.cache.SetSubCache(service.Name, subCache, subCachePath...) - kd.reverseRecordMap[service.Spec.ClusterIP] = reverseRecord - kd.clusterIPServiceMap[service.Spec.ClusterIP] = service -} - -func (kd *KubeDNS) generateRecordsForHeadlessService(e *v1.Endpoints, svc *v1.Service) error { - subCache := treecache.NewTreeCache() - glog.V(4).Infof("Endpoints Annotations: %v", e.Annotations) - for idx := range e.Subsets { - for subIdx := range e.Subsets[idx].Addresses { - address := &e.Subsets[idx].Addresses[subIdx] - endpointIP := address.IP - recordValue, endpointName := util.GetSkyMsg(endpointIP, 0) - if hostLabel, exists := getHostname(address); exists { - endpointName = hostLabel - } - subCache.SetEntry(endpointName, recordValue, kd.fqdn(svc, endpointName)) - for portIdx := range e.Subsets[idx].Ports { - endpointPort := &e.Subsets[idx].Ports[portIdx] - if endpointPort.Name != "" && endpointPort.Protocol != "" { - srvValue := kd.generateSRVRecordValue(svc, int(endpointPort.Port), endpointName) - glog.V(2).Infof("Added SRV record %+v", srvValue) - - l := []string{"_" + strings.ToLower(string(endpointPort.Protocol)), "_" + endpointPort.Name} - subCache.SetEntry(endpointName, srvValue, kd.fqdn(svc, append(l, endpointName)...), l...) - } - } - } - } - subCachePath := append(kd.domainPath, serviceSubdomain, svc.Namespace) - kd.cacheLock.Lock() - defer kd.cacheLock.Unlock() - kd.cache.SetSubCache(svc.Name, subCache, subCachePath...) - return nil -} - -func getHostname(address *v1.EndpointAddress) (string, bool) { - if len(address.Hostname) > 0 { - return address.Hostname, true - } - return "", false -} - -func (kd *KubeDNS) generateSRVRecordValue(svc *v1.Service, portNumber int, labels ...string) *skymsg.Service { - host := strings.Join([]string{svc.Name, svc.Namespace, serviceSubdomain, kd.domain}, ".") - for _, cNameLabel := range labels { - host = cNameLabel + "." + host - } - recordValue, _ := util.GetSkyMsg(host, portNumber) - return recordValue -} - -// Generates skydns records for a headless service. -func (kd *KubeDNS) newHeadlessService(service *v1.Service) error { - // Create an A record for every pod in the service. - // This record must be periodically updated. - // Format is as follows: - // For a service x, with pods a and b create DNS records, - // a.x.ns.domain. and, b.x.ns.domain. - key, err := kcache.MetaNamespaceKeyFunc(service) - if err != nil { - return err - } - e, exists, err := kd.endpointsStore.GetByKey(key) - if err != nil { - return fmt.Errorf("failed to get endpoints object from endpoints store - %v", err) - } - if !exists { - glog.V(1).Infof("Could not find endpoints for service %q in namespace %q. DNS records will be created once endpoints show up.", - service.Name, service.Namespace) - return nil - } - if e, ok := e.(*v1.Endpoints); ok { - return kd.generateRecordsForHeadlessService(e, service) - } - return nil -} - -// Generates skydns records for an ExternalName service. -func (kd *KubeDNS) newExternalNameService(service *v1.Service) { - // Create a CNAME record for the service's ExternalName. - // TODO: TTL? - recordValue, _ := util.GetSkyMsg(service.Spec.ExternalName, 0) - cachePath := append(kd.domainPath, serviceSubdomain, service.Namespace) - fqdn := kd.fqdn(service) - glog.V(2).Infof("newExternalNameService: storing key %s with value %v as %s under %v", - service.Name, recordValue, fqdn, cachePath) - kd.cacheLock.Lock() - defer kd.cacheLock.Unlock() - // Store the service name directly as the leaf key - kd.cache.SetEntry(service.Name, recordValue, fqdn, cachePath...) -} - -// Records responds with DNS records that match the given name, in a format -// understood by the skydns server. If "exact" is true, a single record -// matching the given name is returned, otherwise all records stored under -// the subtree matching the name are returned. -func (kd *KubeDNS) Records(name string, exact bool) (retval []skymsg.Service, err error) { - glog.V(3).Infof("Query for %q, exact: %v", name, exact) - - trimmed := strings.TrimRight(name, ".") - segments := strings.Split(trimmed, ".") - isFederationQuery := false - federationSegments := []string{} - - if !exact && kd.isFederationQuery(segments) { - glog.V(3).Infof("Received federation query, trying local service first") - // Try querying the non-federation (local) service first. Will try - // the federation one later, if this fails. - isFederationQuery = true - federationSegments = append(federationSegments, segments...) - // To try local service, remove federation name from segments. - // Federation name is 3rd in the segment (after service name and - // namespace). - segments = append(segments[:2], segments[3:]...) - } - - path := util.ReverseArray(segments) - records, err := kd.getRecordsForPath(path, exact) - - if err != nil { - return nil, err - } - - if isFederationQuery { - return kd.recordsForFederation(records, path, exact, federationSegments) - } else if len(records) > 0 { - glog.V(4).Infof("Records for %v: %v", name, records) - return records, nil - } - - glog.V(3).Infof("No record found for %v", name) - return nil, etcd.Error{Code: etcd.ErrorCodeKeyNotFound} -} - -func (kd *KubeDNS) recordsForFederation(records []skymsg.Service, path []string, exact bool, federationSegments []string) (retval []skymsg.Service, err error) { - // For federation query, verify that the local service has endpoints. - validRecord := false - for _, val := range records { - // We know that a headless service has endpoints for sure if a - // record was returned for it. The record contains endpoint - // IPs. So nothing to check for headless services. - // - // TODO: this access to the cluster IP map does not seem to be - // threadsafe. - if !kd.isHeadlessServiceRecord(&val) { - ok, err := kd.serviceWithClusterIPHasEndpoints(&val) - if err != nil { - glog.V(2).Infof( - "Federation: error finding if service has endpoint: %v", err) - continue - } - if !ok { - glog.V(2).Infof("Federation: skipping record since service has no endpoint: %v", val) - continue - } - } - validRecord = true - break - } - - if validRecord { - // There is a local service with valid endpoints, return its CNAME. - name := strings.Join(util.ReverseArray(path), ".") - // Ensure that this name that we are returning as a CNAME response - // is a fully qualified domain name so that the client's resolver - // library doesn't have to go through its search list all over - // again. - if !strings.HasSuffix(name, ".") { - name = name + "." - } - glog.V(3).Infof( - "Federation: Returning CNAME for local service: %v", name) - return []skymsg.Service{{Host: name}}, nil - } - - // If the name query is not an exact query and does not match any - // records in the local store, attempt to send a federation redirect - // (CNAME) response. - if !exact { - glog.V(3).Infof( - "Federation: Did not find a local service. Trying federation redirect (CNAME)") - return kd.federationRecords(util.ReverseArray(federationSegments)) - } - - return nil, etcd.Error{Code: etcd.ErrorCodeKeyNotFound} -} - -func (kd *KubeDNS) getRecordsForPath(path []string, exact bool) ([]skymsg.Service, error) { - if kd.isPodRecord(path) { - ip, err := kd.getPodIP(path) - if err == nil { - skyMsg, _ := util.GetSkyMsg(ip, 0) - return []skymsg.Service{*skyMsg}, nil - } - return nil, err - } - - if exact { - key := path[len(path)-1] - if key == "" { - return []skymsg.Service{}, nil - } - kd.cacheLock.RLock() - defer kd.cacheLock.RUnlock() - if record, ok := kd.cache.GetEntry(key, path[:len(path)-1]...); ok { - glog.V(3).Infof("Exact match %v for %v received from cache", record, path[:len(path)-1]) - return []skymsg.Service{*(record.(*skymsg.Service))}, nil - } - - glog.V(3).Infof("Exact match for %v not found in cache", path) - return nil, etcd.Error{Code: etcd.ErrorCodeKeyNotFound} - } - - kd.cacheLock.RLock() - defer kd.cacheLock.RUnlock() - records := kd.cache.GetValuesForPathWithWildcards(path...) - glog.V(3).Infof("Found %d records for %v in the cache", len(records), path) - - retval := []skymsg.Service{} - for _, val := range records { - retval = append(retval, *val) - } - - glog.V(4).Infof("getRecordsForPath retval=%+v, path=%v", retval, path) - - return retval, nil -} - -// Returns true if the given record corresponds to a headless service. -// Important: Assumes that we already have the cacheLock. Callers responsibility to acquire it. -// This is because the code will panic, if we try to acquire it again if we already have it. -func (kd *KubeDNS) isHeadlessServiceRecord(msg *skymsg.Service) bool { - // If it is not a headless service, then msg.Host will be the cluster IP. - // So we can check if msg.host exists in our clusterIPServiceMap. - _, ok := kd.clusterIPServiceMap[msg.Host] - // It is headless service if no record was found. - return !ok -} - -// Returns true if the service corresponding to the given message has endpoints. -// Note: Works only for services with ClusterIP. Will return an error for headless service (service without a clusterIP). -// Important: Assumes that we already have the cacheLock. Callers responsibility to acquire it. -// This is because the code will panic, if we try to acquire it again if we already have it. -func (kd *KubeDNS) serviceWithClusterIPHasEndpoints(msg *skymsg.Service) (bool, error) { - svc, ok := kd.clusterIPServiceMap[msg.Host] - if !ok { - // It is a headless service. - return false, fmt.Errorf("method not expected to be called for headless service") - } - key, err := kcache.MetaNamespaceKeyFunc(svc) - if err != nil { - return false, err - } - e, exists, err := kd.endpointsStore.GetByKey(key) - if err != nil { - return false, fmt.Errorf("failed to get endpoints object from endpoints store - %v", err) - } - if !exists { - return false, nil - } - if e, ok := e.(*v1.Endpoints); ok { - return len(e.Subsets) > 0, nil - } - return false, fmt.Errorf("unexpected: found non-endpoint object in endpoint store: %v", e) -} - -// ReverseRecords performs a reverse lookup for the given name. -func (kd *KubeDNS) ReverseRecord(name string) (*skymsg.Service, error) { - glog.V(3).Infof("Query for ReverseRecord %q", name) - - // if portalIP is not a valid IP, the reverseRecordMap lookup will fail - portalIP, ok := util.ExtractIP(name) - if !ok { - return nil, fmt.Errorf("does not support reverse lookup for %s", name) - } - - kd.cacheLock.RLock() - defer kd.cacheLock.RUnlock() - if reverseRecord, ok := kd.reverseRecordMap[portalIP]; ok { - return reverseRecord, nil - } - - return nil, fmt.Errorf("must be exactly one service record") -} - -// e.g {"local", "cluster", "pod", "default", "10-0-0-1"} -func (kd *KubeDNS) isPodRecord(path []string) bool { - if len(path) != len(kd.domainPath)+3 { - return false - } - if path[len(kd.domainPath)] != "pod" { - return false - } - for _, segment := range path { - if segment == "*" { - return false - } - } - return true -} - -func (kd *KubeDNS) getPodIP(path []string) (string, error) { - ipStr := path[len(path)-1] - ip := strings.Replace(ipStr, "-", ".", -1) - if parsed := net.ParseIP(ip); parsed != nil { - return ip, nil - } - return "", fmt.Errorf("Invalid IP Address %v", ip) -} - -// isFederationQuery checks if the given query `path` matches the federated service query pattern. -// The conjunction of the following conditions forms the test for the federated service query -// pattern: -// 1. `path` has exactly 4+len(domainPath) segments: mysvc.myns.myfederation.svc.domain.path. -// 2. Service name component must be a valid RFC 1035 name. -// 3. Namespace component must be a valid RFC 1123 name. -// 4. Federation component must also be a valid RFC 1123 name. -// 5. Fourth segment is exactly "svc" -// 6. The remaining segments match kd.domainPath. -// 7. And federation must be one of the listed federations in the config. -// Note: Because of the above conditions, this method will treat wildcard queries such as -// *.mysvc.myns.myfederation.svc.domain.path as non-federation queries. -// We can add support for wildcard queries later, if needed. -func (kd *KubeDNS) isFederationQuery(path []string) bool { - if len(path) != 4+len(kd.domainPath) { - glog.V(4).Infof("Not a federation query: len(%q) != 4+len(%q)", path, kd.domainPath) - return false - } - if errs := validation.IsDNS1035Label(path[0]); len(errs) != 0 { - glog.V(4).Infof("Not a federation query: %q is not an RFC 1035 label: %q", - path[0], errs) - return false - } - if errs := validation.IsDNS1123Label(path[1]); len(errs) != 0 { - glog.V(4).Infof("Not a federation query: %q is not an RFC 1123 label: %q", - path[1], errs) - return false - } - if errs := validation.IsDNS1123Label(path[2]); len(errs) != 0 { - glog.V(4).Infof("Not a federation query: %q is not an RFC 1123 label: %q", - path[2], errs) - return false - } - if path[3] != serviceSubdomain { - glog.V(4).Infof("Not a federation query: %q != %q (serviceSubdomain)", - path[3], serviceSubdomain) - return false - } - for i, domComp := range kd.domainPath { - // kd.domainPath is reversed, so we need to look in the `path` in the reverse order. - if domComp != path[len(path)-i-1] { - glog.V(4).Infof("Not a federation query: kd.domainPath[%d] != path[%d] (%q != %q)", - i, len(path)-i-1, domComp, path[len(path)-i-1]) - return false - } - } - - kd.configLock.RLock() - defer kd.configLock.RUnlock() - - if _, ok := kd.config.Federations[path[2]]; !ok { - glog.V(4).Infof("Not a federation query: label %q not found", path[2]) - return false - } - - return true -} - -// federationRecords checks if the given `queryPath` is for a federated service and if it is, -// it returns a CNAME response containing the cluster zone name and federation domain name -// suffix. -func (kd *KubeDNS) federationRecords(queryPath []string) ([]skymsg.Service, error) { - // `queryPath` is a reversed-array of the queried name, reverse it back to make it easy - // to follow through this code and reduce confusion. There is no reason for it to be - // reversed here. - path := util.ReverseArray(queryPath) - - // Check if the name query matches the federation query pattern. - if !kd.isFederationQuery(path) { - return nil, etcd.Error{Code: etcd.ErrorCodeKeyNotFound} - } - - // Now that we have already established that the query is a federation query, remove the local - // domain path components, i.e. kd.domainPath, from the query. - path = path[:len(path)-len(kd.domainPath)] - - // Append the zone name (zone in the cloud provider terminology, not a DNS - // zone) and the region name. - zone, region, err := kd.getClusterZoneAndRegion() - if err != nil { - return nil, fmt.Errorf("failed to obtain the cluster zone and region: %v", err) - } - path = append(path, zone, region) - - // We have already established that the map entry exists for the given federation, - // we just need to retrieve the domain name, validate it and append it to the path. - kd.configLock.RLock() - domain := kd.config.Federations[path[2]] - kd.configLock.RUnlock() - - // We accept valid subdomains as well, so just let all the valid subdomains. - if len(validation.IsDNS1123Subdomain(domain)) != 0 { - return nil, fmt.Errorf("%s is not a valid domain name for federation %s", domain, path[2]) - } - name := strings.Join(append(path, domain), ".") - - // Ensure that this name that we are returning as a CNAME response is a fully qualified - // domain name so that the client's resolver library doesn't have to go through its - // search list all over again. - if !strings.HasSuffix(name, ".") { - name = name + "." - } - return []skymsg.Service{{Host: name}}, nil -} - -// getClusterZoneAndRegion returns the name of the zone and the region the -// cluster is running in. It arbitrarily selects a node and reads the failure -// domain label on the node. An alternative is to obtain this pod's -// (i.e. kube-dns pod's) name using the downward API, get the pod, get the -// node the pod is bound to and retrieve that node's labels. But even just by -// reading those steps, it looks complex and it is not entirely clear what -// that complexity is going to buy us. So taking a simpler approach here. -// Also note that zone here means the zone in cloud provider terminology, not -// the DNS zone. -func (kd *KubeDNS) getClusterZoneAndRegion() (string, string, error) { - var node *v1.Node - - objs := kd.nodesStore.List() - if len(objs) > 0 { - var ok bool - if node, ok = objs[0].(*v1.Node); !ok { - return "", "", fmt.Errorf("expected node object, got: %T", objs[0]) - } - } else { - // An alternative to listing nodes each time is to set a watch, but that is totally - // wasteful in case of non-federated independent Kubernetes clusters. So carefully - // proceeding here. - // TODO(madhusudancs): Move this to external/v1 API. - nodeList, err := kd.kubeClient.Core().Nodes().List(v1.ListOptions{}) - if err != nil || len(nodeList.Items) == 0 { - return "", "", fmt.Errorf("failed to retrieve the cluster nodes: %v", err) - } - - // Select a node (arbitrarily the first node) that has - // `LabelZoneFailureDomain` and `LabelZoneRegion` set. - for _, nodeItem := range nodeList.Items { - _, zfound := nodeItem.Labels[metav1.LabelZoneFailureDomain] - _, rfound := nodeItem.Labels[metav1.LabelZoneRegion] - if !zfound || !rfound { - continue - } - // Make a copy of the node, don't rely on the loop variable. - node = &(*(&nodeItem)) - if err := kd.nodesStore.Add(node); err != nil { - return "", "", fmt.Errorf("couldn't add the retrieved node to the cache: %v", err) - } - // Node is found, break out of the loop. - break - } - } - - if node == nil { - return "", "", fmt.Errorf("Could not find any nodes") - } - - zone, ok := node.Labels[metav1.LabelZoneFailureDomain] - if !ok || zone == "" { - return "", "", fmt.Errorf("unknown cluster zone") - } - region, ok := node.Labels[metav1.LabelZoneRegion] - if !ok || region == "" { - return "", "", fmt.Errorf("unknown cluster region") - } - return zone, region, nil -} - -func getServiceFQDN(domain string, service *v1.Service) string { - return strings.Join( - []string{service.Name, service.Namespace, serviceSubdomain, domain}, ".") -} diff --git a/pkg/dns/dns_test.go b/pkg/dns/dns_test.go deleted file mode 100644 index 31173c7955f..00000000000 --- a/pkg/dns/dns_test.go +++ /dev/null @@ -1,839 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package dns - -import ( - "fmt" - "net" - "reflect" - "strings" - "sync" - "testing" - "time" - - etcd "github.com/coreos/etcd/client" - "github.com/miekg/dns" - skymsg "github.com/skynetservices/skydns/msg" - skyserver "github.com/skynetservices/skydns/server" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "k8s.io/client-go/kubernetes/fake" - "k8s.io/client-go/pkg/api/v1" - metav1 "k8s.io/client-go/pkg/apis/meta/v1" - "k8s.io/client-go/tools/cache" - - "k8s.io/kubernetes/pkg/dns/config" - "k8s.io/kubernetes/pkg/dns/treecache" - "k8s.io/kubernetes/pkg/dns/util" - "k8s.io/kubernetes/pkg/util/sets" -) - -const ( - testDomain = "cluster.local." - testService = "testservice" - testNamespace = "default" - testExternalName = "foo.bar.example.com" -) - -func newKubeDNS() *KubeDNS { - return &KubeDNS{ - domain: testDomain, - domainPath: util.ReverseArray(strings.Split(strings.TrimRight(testDomain, "."), ".")), - - endpointsStore: cache.NewStore(cache.MetaNamespaceKeyFunc), - servicesStore: cache.NewStore(cache.MetaNamespaceKeyFunc), - nodesStore: cache.NewStore(cache.MetaNamespaceKeyFunc), - - cache: treecache.NewTreeCache(), - reverseRecordMap: make(map[string]*skymsg.Service), - clusterIPServiceMap: make(map[string]*v1.Service), - cacheLock: sync.RWMutex{}, - - config: config.NewDefaultConfig(), - configLock: sync.RWMutex{}, - configSync: config.NewNopSync(config.NewDefaultConfig()), - } -} - -func TestPodDns(t *testing.T) { - const ( - testPodIP = "1.2.3.4" - sanitizedPodIP = "1-2-3-4" - ) - kd := newKubeDNS() - - records, err := kd.Records(sanitizedPodIP+".default.pod."+kd.domain, false) - require.NoError(t, err) - assert.Equal(t, 1, len(records)) - assert.Equal(t, testPodIP, records[0].Host) -} - -func TestUnnamedSinglePortService(t *testing.T) { - kd := newKubeDNS() - s := newService(testNamespace, testService, "1.2.3.4", "", 80) - // Add the service - kd.newService(s) - assertDNSForClusterIP(t, kd, s) - assertReverseRecord(t, kd, s) - // Delete the service - kd.removeService(s) - assertNoDNSForClusterIP(t, kd, s) - assertNoReverseRecord(t, kd, s) -} - -func TestNamedSinglePortService(t *testing.T) { - const ( - portName1 = "http1" - portName2 = "http2" - ) - kd := newKubeDNS() - s := newService(testNamespace, testService, "1.2.3.4", portName1, 80) - // Add the service - kd.newService(s) - assertDNSForClusterIP(t, kd, s) - assertSRVForNamedPort(t, kd, s, portName1) - - newService := *s - // update the portName of the service - newService.Spec.Ports[0].Name = portName2 - kd.updateService(s, &newService) - assertDNSForClusterIP(t, kd, s) - assertSRVForNamedPort(t, kd, s, portName2) - assertNoSRVForNamedPort(t, kd, s, portName1) - - // Delete the service - kd.removeService(s) - assertNoDNSForClusterIP(t, kd, s) - assertNoSRVForNamedPort(t, kd, s, portName1) - assertNoSRVForNamedPort(t, kd, s, portName2) -} - -func assertARecordsMatchIPs(t *testing.T, records []dns.RR, ips ...string) { - expectedEndpoints := sets.NewString(ips...) - gotEndpoints := sets.NewString() - for _, r := range records { - if a, ok := r.(*dns.A); !ok { - t.Errorf("Expected A record, got %#v", a) - } else { - gotEndpoints.Insert(a.A.String()) - } - } - if !gotEndpoints.Equal(expectedEndpoints) { - t.Errorf("Expected %v got %v", expectedEndpoints, gotEndpoints) - } -} - -func assertSRVRecordsMatchTarget(t *testing.T, records []dns.RR, targets ...string) { - expectedTargets := sets.NewString(targets...) - gotTargets := sets.NewString() - for _, r := range records { - if srv, ok := r.(*dns.SRV); !ok { - t.Errorf("Expected SRV record, got %+v", srv) - } else { - gotTargets.Insert(srv.Target) - } - } - if !gotTargets.Equal(expectedTargets) { - t.Errorf("Expected %v got %v", expectedTargets, gotTargets) - } -} - -func assertSRVRecordsMatchPort(t *testing.T, records []dns.RR, port ...int) { - expectedPorts := sets.NewInt(port...) - gotPorts := sets.NewInt() - for _, r := range records { - if srv, ok := r.(*dns.SRV); !ok { - t.Errorf("Expected SRV record, got %+v", srv) - } else { - gotPorts.Insert(int(srv.Port)) - t.Logf("got %+v", srv) - } - } - if !gotPorts.Equal(expectedPorts) { - t.Errorf("Expected %v got %v", expectedPorts, gotPorts) - } -} - -func TestSkySimpleSRVLookup(t *testing.T) { - kd := newKubeDNS() - skydnsConfig := &skyserver.Config{Domain: testDomain, DnsAddr: "0.0.0.0:53"} - skyserver.SetDefaults(skydnsConfig) - s := skyserver.New(kd, skydnsConfig) - - service := newHeadlessService() - endpointIPs := []string{"10.0.0.1", "10.0.0.2"} - endpoints := newEndpoints(service, newSubsetWithOnePort("", 80, endpointIPs...)) - assert.NoError(t, kd.endpointsStore.Add(endpoints)) - kd.newService(service) - - name := strings.Join([]string{testService, testNamespace, "svc", testDomain}, ".") - question := dns.Question{Name: name, Qtype: dns.TypeSRV, Qclass: dns.ClassINET} - - rec, extra, err := s.SRVRecords(question, name, 512, false) - if err != nil { - t.Fatalf("Failed srv record lookup on service with fqdn %v", name) - } - assertARecordsMatchIPs(t, extra, endpointIPs...) - targets := []string{} - for _, eip := range endpointIPs { - // A portal service is always created with a port of '0' - targets = append(targets, - fmt.Sprintf("%x.%v", - util.HashServiceRecord(util.NewServiceRecord(eip, 0)), name)) - } - assertSRVRecordsMatchTarget(t, rec, targets...) -} - -func TestSkyPodHostnameSRVLookup(t *testing.T) { - kd := newKubeDNS() - skydnsConfig := &skyserver.Config{Domain: testDomain, DnsAddr: "0.0.0.0:53"} - skyserver.SetDefaults(skydnsConfig) - s := skyserver.New(kd, skydnsConfig) - - service := newHeadlessService() - endpointIPs := []string{"10.0.0.1", "10.0.0.2"} - endpoints := newEndpoints( - service, - newSubsetWithOnePortWithHostname("", 80, true, endpointIPs...)) - assert.NoError(t, kd.endpointsStore.Add(endpoints)) - kd.newService(service) - name := strings.Join([]string{testService, testNamespace, "svc", testDomain}, ".") - question := dns.Question{Name: name, Qtype: dns.TypeSRV, Qclass: dns.ClassINET} - - rec, _, err := s.SRVRecords(question, name, 512, false) - if err != nil { - t.Fatalf("Failed srv record lookup on service with fqdn %v", name) - } - targets := []string{} - for i := range endpointIPs { - targets = append(targets, fmt.Sprintf("%v.%v", fmt.Sprintf("ep-%d", i), name)) - } - assertSRVRecordsMatchTarget(t, rec, targets...) -} - -func TestSkyNamedPortSRVLookup(t *testing.T) { - kd := newKubeDNS() - skydnsConfig := &skyserver.Config{Domain: testDomain, DnsAddr: "0.0.0.0:53"} - skyserver.SetDefaults(skydnsConfig) - s := skyserver.New(kd, skydnsConfig) - - service := newHeadlessService() - eip := "10.0.0.1" - endpoints := newEndpoints(service, newSubsetWithOnePort("http", 8081, eip)) - assert.NoError(t, kd.endpointsStore.Add(endpoints)) - kd.newService(service) - - name := strings.Join([]string{"_http", "_tcp", testService, testNamespace, "svc", testDomain}, ".") - question := dns.Question{Name: name, Qtype: dns.TypeSRV, Qclass: dns.ClassINET} - rec, extra, err := s.SRVRecords(question, name, 512, false) - if err != nil { - t.Fatalf("Failed srv record lookup on service with fqdn %v", name) - } - - svcDomain := strings.Join([]string{testService, testNamespace, "svc", testDomain}, ".") - assertARecordsMatchIPs(t, extra, eip) - assertSRVRecordsMatchTarget( - t, rec, fmt.Sprintf("%x.%v", util.HashServiceRecord(util.NewServiceRecord(eip, 0)), svcDomain)) - assertSRVRecordsMatchPort(t, rec, 8081) -} - -func TestSimpleExternalService(t *testing.T) { - kd := newKubeDNS() - s := newExternalNameService() - assert.NoError(t, kd.servicesStore.Add(s)) - - kd.newService(s) - assertDNSForExternalService(t, kd, s) - kd.removeService(s) - assertNoDNSForExternalService(t, kd, s) -} - -func TestSimpleHeadlessService(t *testing.T) { - kd := newKubeDNS() - s := newHeadlessService() - assert.NoError(t, kd.servicesStore.Add(s)) - endpoints := newEndpoints(s, newSubsetWithOnePort("", 80, "10.0.0.1", "10.0.0.2"), newSubsetWithOnePort("", 8080, "10.0.0.3", "10.0.0.4")) - - assert.NoError(t, kd.endpointsStore.Add(endpoints)) - kd.newService(s) - assertDNSForHeadlessService(t, kd, endpoints) - kd.removeService(s) - assertNoDNSForHeadlessService(t, kd, s) -} - -func TestHeadlessServiceWithNamedPorts(t *testing.T) { - kd := newKubeDNS() - service := newHeadlessService() - // add service to store - assert.NoError(t, kd.servicesStore.Add(service)) - endpoints := newEndpoints(service, newSubsetWithTwoPorts("http1", 80, "http2", 81, "10.0.0.1", "10.0.0.2"), - newSubsetWithOnePort("https", 443, "10.0.0.3", "10.0.0.4")) - - // We expect 10 records. 6 SRV records. 4 POD records. - // add endpoints - assert.NoError(t, kd.endpointsStore.Add(endpoints)) - - // add service - kd.newService(service) - assertDNSForHeadlessService(t, kd, endpoints) - assertSRVForHeadlessService(t, kd, service, endpoints) - - // reduce endpoints - endpoints.Subsets = endpoints.Subsets[:1] - kd.handleEndpointAdd(endpoints) - // We expect 6 records. 4 SRV records. 2 POD records. - assertDNSForHeadlessService(t, kd, endpoints) - assertSRVForHeadlessService(t, kd, service, endpoints) - - kd.removeService(service) - assertNoDNSForHeadlessService(t, kd, service) -} - -func TestHeadlessServiceEndpointsUpdate(t *testing.T) { - kd := newKubeDNS() - service := newHeadlessService() - // add service to store - assert.NoError(t, kd.servicesStore.Add(service)) - - endpoints := newEndpoints(service, newSubsetWithOnePort("", 80, "10.0.0.1", "10.0.0.2")) - // add endpoints to store - assert.NoError(t, kd.endpointsStore.Add(endpoints)) - - // add service - kd.newService(service) - assertDNSForHeadlessService(t, kd, endpoints) - - // increase endpoints - endpoints.Subsets = append(endpoints.Subsets, - newSubsetWithOnePort("", 8080, "10.0.0.3", "10.0.0.4"), - ) - // expected DNSRecords = 4 - kd.handleEndpointAdd(endpoints) - assertDNSForHeadlessService(t, kd, endpoints) - - // remove all endpoints - endpoints.Subsets = []v1.EndpointSubset{} - kd.handleEndpointAdd(endpoints) - assertNoDNSForHeadlessService(t, kd, service) - - // remove service - kd.removeService(service) - assertNoDNSForHeadlessService(t, kd, service) -} - -func TestHeadlessServiceWithDelayedEndpointsAddition(t *testing.T) { - kd := newKubeDNS() - // create service - service := newHeadlessService() - - // add service to store - assert.NoError(t, kd.servicesStore.Add(service)) - - // add service - kd.newService(service) - assertNoDNSForHeadlessService(t, kd, service) - - // create endpoints - endpoints := newEndpoints(service, newSubsetWithOnePort("", 80, "10.0.0.1", "10.0.0.2")) - - // add endpoints to store - assert.NoError(t, kd.endpointsStore.Add(endpoints)) - - // add endpoints - kd.handleEndpointAdd(endpoints) - - assertDNSForHeadlessService(t, kd, endpoints) - - // remove service - kd.removeService(service) - assertNoDNSForHeadlessService(t, kd, service) -} - -// Verifies that a single record with host "a" is returned for query "q". -func verifyRecord(q, a string, t *testing.T, kd *KubeDNS) { - records, err := kd.Records(q, false) - require.NoError(t, err) - assert.Equal(t, 1, len(records)) - assert.Equal(t, a, records[0].Host) -} - -const federatedServiceFQDN = "testservice.default.myfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.example.com." - -// Verifies that querying KubeDNS for a headless federation service -// returns the DNS hostname when a local service does not exist and -// returns the endpoint IP when a local service exists. -func TestFederationHeadlessService(t *testing.T) { - kd := newKubeDNS() - kd.config.Federations = map[string]string{ - "myfederation": "example.com", - } - kd.kubeClient = fake.NewSimpleClientset(newNodes()) - - // Verify that querying for federation service returns a federation domain name. - verifyRecord("testservice.default.myfederation.svc.cluster.local.", - federatedServiceFQDN, t, kd) - - // Add a local service without any endpoint. - s := newHeadlessService() - assert.NoError(t, kd.servicesStore.Add(s)) - kd.newService(s) - - // Verify that querying for federation service still returns the federation domain name. - verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"), - federatedServiceFQDN, t, kd) - - // Now add an endpoint. - endpoints := newEndpoints(s, newSubsetWithOnePort("", 80, "10.0.0.1")) - assert.NoError(t, kd.endpointsStore.Add(endpoints)) - kd.updateService(s, s) - - // Verify that querying for federation service returns the local service domain name this time. - verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"), - "testservice.default.svc.cluster.local.", t, kd) - - // Delete the endpoint. - endpoints.Subsets = []v1.EndpointSubset{} - kd.handleEndpointAdd(endpoints) - kd.updateService(s, s) - - // Verify that querying for federation service returns the federation domain name again. - verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"), - federatedServiceFQDN, t, kd) -} - -// Verifies that querying KubeDNS for a federation service returns the -// DNS hostname if no endpoint exists and returns the local cluster IP -// if endpoints exist. -func TestFederationService(t *testing.T) { - kd := newKubeDNS() - kd.config.Federations = map[string]string{ - "myfederation": "example.com", - } - kd.kubeClient = fake.NewSimpleClientset(newNodes()) - - // Verify that querying for federation service returns the federation domain name. - verifyRecord("testservice.default.myfederation.svc.cluster.local.", - federatedServiceFQDN, t, kd) - - // Add a local service without any endpoint. - s := newService(testNamespace, testService, "1.2.3.4", "", 80) - assert.NoError(t, kd.servicesStore.Add(s)) - kd.newService(s) - - // Verify that querying for federation service still returns the federation domain name. - verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"), - federatedServiceFQDN, t, kd) - - // Now add an endpoint. - endpoints := newEndpoints(s, newSubsetWithOnePort("", 80, "10.0.0.1")) - assert.NoError(t, kd.endpointsStore.Add(endpoints)) - kd.updateService(s, s) - - // Verify that querying for federation service returns the local service domain name this time. - verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"), - "testservice.default.svc.cluster.local.", t, kd) - - // Remove the endpoint. - endpoints.Subsets = []v1.EndpointSubset{} - kd.handleEndpointAdd(endpoints) - kd.updateService(s, s) - - // Verify that querying for federation service returns the federation domain name again. - verifyRecord(getFederationServiceFQDN(kd, s, "myfederation"), - federatedServiceFQDN, t, kd) -} - -func TestFederationQueryWithoutCache(t *testing.T) { - kd := newKubeDNS() - kd.config.Federations = map[string]string{ - "myfederation": "example.com", - "secondfederation": "second.example.com", - } - kd.kubeClient = fake.NewSimpleClientset(newNodes()) - - testValidFederationQueries(t, kd) - testInvalidFederationQueries(t, kd) -} - -func TestFederationQueryWithCache(t *testing.T) { - kd := newKubeDNS() - kd.config.Federations = map[string]string{ - "myfederation": "example.com", - "secondfederation": "second.example.com", - } - - // Add a node to the cache. - nodeList := newNodes() - if err := kd.nodesStore.Add(&nodeList.Items[1]); err != nil { - t.Errorf("failed to add the node to the cache: %v", err) - } - - testValidFederationQueries(t, kd) - testInvalidFederationQueries(t, kd) -} - -func testValidFederationQueries(t *testing.T, kd *KubeDNS) { - queries := []struct { - q string - a string - }{ - // Federation suffix is just a domain. - { - q: "mysvc.myns.myfederation.svc.cluster.local.", - a: "mysvc.myns.myfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.example.com.", - }, - // Federation suffix is a subdomain. - { - q: "secsvc.default.secondfederation.svc.cluster.local.", - a: "secsvc.default.secondfederation.svc.testcontinent-testreg-testzone.testcontinent-testreg.second.example.com.", - }, - } - - for _, query := range queries { - verifyRecord(query.q, query.a, t, kd) - } -} - -func testInvalidFederationQueries(t *testing.T, kd *KubeDNS) { - noAnswerQueries := []string{ - "mysvc.myns.svc.cluster.local.", - "mysvc.default.nofederation.svc.cluster.local.", - } - for _, q := range noAnswerQueries { - records, err := kd.Records(q, false) - if err == nil { - t.Errorf("expected not found error, got nil") - } - if etcdErr, ok := err.(etcd.Error); !ok || etcdErr.Code != etcd.ErrorCodeKeyNotFound { - t.Errorf("expected not found error, got %v", err) - } - assert.Equal(t, 0, len(records)) - } -} - -func checkConfigEqual(t *testing.T, kd *KubeDNS, expected *config.Config) { - const timeout = time.Duration(5) - - start := time.Now() - - ok := false - - for time.Since(start) < timeout*time.Second { - kd.configLock.RLock() - isEqual := reflect.DeepEqual(expected.Federations, kd.config.Federations) - kd.configLock.RUnlock() - - if isEqual { - ok = true - break - } - } - - if !ok { - t.Errorf("Federations should be %v, got %v", - expected.Federations, kd.config.Federations) - } -} - -func TestConfigSync(t *testing.T) { - kd := newKubeDNS() - mockSync := config.NewMockSync( - &config.Config{Federations: make(map[string]string)}, nil) - kd.configSync = mockSync - - kd.startConfigMapSync() - - checkConfigEqual(t, kd, &config.Config{Federations: make(map[string]string)}) - // update - mockSync.Chan <- &config.Config{Federations: map[string]string{"name1": "domain1"}} - checkConfigEqual(t, kd, &config.Config{Federations: map[string]string{"name1": "domain1"}}) - // update - mockSync.Chan <- &config.Config{Federations: map[string]string{"name2": "domain2"}} - checkConfigEqual(t, kd, &config.Config{Federations: map[string]string{"name2": "domain2"}}) -} - -func TestConfigSyncInitialMap(t *testing.T) { - // start with different initial map - kd := newKubeDNS() - mockSync := config.NewMockSync( - &config.Config{Federations: map[string]string{"name3": "domain3"}}, nil) - kd.configSync = mockSync - - kd.startConfigMapSync() - checkConfigEqual(t, kd, &config.Config{Federations: map[string]string{"name3": "domain3"}}) -} - -func newNodes() *v1.NodeList { - return &v1.NodeList{ - Items: []v1.Node{ - // Node without annotation. - { - ObjectMeta: v1.ObjectMeta{ - Name: "testnode-0", - }, - }, - { - ObjectMeta: v1.ObjectMeta{ - Name: "testnode-1", - Labels: map[string]string{ - // Note: The zone name here is an arbitrary string and doesn't exactly follow the - // format used by the cloud providers to name their zones. But that shouldn't matter - // for these tests here. - metav1.LabelZoneFailureDomain: "testcontinent-testreg-testzone", - metav1.LabelZoneRegion: "testcontinent-testreg", - }, - }, - }, - }, - } -} - -func newService(namespace, serviceName, clusterIP, portName string, portNumber int32) *v1.Service { - service := v1.Service{ - ObjectMeta: v1.ObjectMeta{ - Name: serviceName, - Namespace: namespace, - }, - Spec: v1.ServiceSpec{ - ClusterIP: clusterIP, - Ports: []v1.ServicePort{ - {Port: portNumber, Name: portName, Protocol: "TCP"}, - }, - }, - } - return &service -} - -func newExternalNameService() *v1.Service { - service := v1.Service{ - ObjectMeta: v1.ObjectMeta{ - Name: testService, - Namespace: testNamespace, - }, - Spec: v1.ServiceSpec{ - ClusterIP: "None", - Type: v1.ServiceTypeExternalName, - ExternalName: testExternalName, - Ports: []v1.ServicePort{ - {Port: 0}, - }, - }, - } - return &service -} - -func newHeadlessService() *v1.Service { - service := v1.Service{ - ObjectMeta: v1.ObjectMeta{ - Name: testService, - Namespace: testNamespace, - }, - Spec: v1.ServiceSpec{ - ClusterIP: "None", - Ports: []v1.ServicePort{ - {Port: 0}, - }, - }, - } - return &service -} - -func newEndpoints(service *v1.Service, subsets ...v1.EndpointSubset) *v1.Endpoints { - endpoints := v1.Endpoints{ - ObjectMeta: service.ObjectMeta, - Subsets: []v1.EndpointSubset{}, - } - - endpoints.Subsets = append(endpoints.Subsets, subsets...) - return &endpoints -} - -func newSubsetWithOnePort(portName string, port int32, ips ...string) v1.EndpointSubset { - return newSubsetWithOnePortWithHostname(portName, port, false, ips...) -} - -func newSubsetWithOnePortWithHostname(portName string, port int32, addHostname bool, ips ...string) v1.EndpointSubset { - subset := newSubset() - subset.Ports = append(subset.Ports, v1.EndpointPort{Port: port, Name: portName, Protocol: "TCP"}) - for i, ip := range ips { - var hostname string - if addHostname { - hostname = fmt.Sprintf("ep-%d", i) - } - subset.Addresses = append(subset.Addresses, v1.EndpointAddress{IP: ip, Hostname: hostname}) - } - return subset -} - -func newSubsetWithTwoPorts(portName1 string, portNumber1 int32, portName2 string, portNumber2 int32, ips ...string) v1.EndpointSubset { - subset := newSubsetWithOnePort(portName1, portNumber1, ips...) - subset.Ports = append(subset.Ports, v1.EndpointPort{Port: portNumber2, Name: portName2, Protocol: "TCP"}) - return subset -} - -func newSubset() v1.EndpointSubset { - subset := v1.EndpointSubset{ - Addresses: []v1.EndpointAddress{}, - Ports: []v1.EndpointPort{}, - } - return subset -} - -func assertSRVForHeadlessService(t *testing.T, kd *KubeDNS, s *v1.Service, e *v1.Endpoints) { - for _, subset := range e.Subsets { - for _, port := range subset.Ports { - records, err := kd.Records(getSRVFQDN(kd, s, port.Name), false) - require.NoError(t, err) - assertRecordPortsMatchPort(t, port.Port, records) - assertCNameRecordsMatchEndpointIPs(t, kd, subset.Addresses, records) - } - } -} - -func assertDNSForHeadlessService(t *testing.T, kd *KubeDNS, e *v1.Endpoints) { - records, err := kd.Records(getEndpointsFQDN(kd, e), false) - require.NoError(t, err) - endpoints := map[string]bool{} - for _, subset := range e.Subsets { - for _, endpointAddress := range subset.Addresses { - endpoints[endpointAddress.IP] = true - } - } - assert.Equal(t, len(endpoints), len(records)) - for _, record := range records { - _, found := endpoints[record.Host] - assert.True(t, found) - } -} - -func assertDNSForExternalService(t *testing.T, kd *KubeDNS, s *v1.Service) { - records, err := kd.Records(getServiceFQDN(kd.domain, s), false) - require.NoError(t, err) - assert.Equal(t, 1, len(records)) - assert.Equal(t, testExternalName, records[0].Host) -} - -func assertRecordPortsMatchPort(t *testing.T, port int32, records []skymsg.Service) { - for _, record := range records { - assert.Equal(t, port, int32(record.Port)) - } -} - -func assertCNameRecordsMatchEndpointIPs(t *testing.T, kd *KubeDNS, e []v1.EndpointAddress, records []skymsg.Service) { - endpoints := map[string]bool{} - for _, endpointAddress := range e { - endpoints[endpointAddress.IP] = true - } - assert.Equal(t, len(e), len(records), "unexpected record count") - for _, record := range records { - _, found := endpoints[getIPForCName(t, kd, record.Host)] - assert.True(t, found, "Did not find endpoint with address:%s", record.Host) - } -} - -func getIPForCName(t *testing.T, kd *KubeDNS, cname string) string { - records, err := kd.Records(cname, false) - require.NoError(t, err) - assert.Equal(t, 1, len(records), "Could not get IP for CNAME record for %s", cname) - assert.NotNil(t, net.ParseIP(records[0].Host), "Invalid IP address %q", records[0].Host) - return records[0].Host -} - -func assertNoDNSForHeadlessService(t *testing.T, kd *KubeDNS, s *v1.Service) { - records, err := kd.Records(getServiceFQDN(kd.domain, s), false) - require.Error(t, err) - assert.Equal(t, 0, len(records)) -} - -func assertNoDNSForExternalService(t *testing.T, kd *KubeDNS, s *v1.Service) { - records, err := kd.Records(getServiceFQDN(kd.domain, s), false) - require.Error(t, err) - assert.Equal(t, 0, len(records)) -} - -func assertSRVForNamedPort(t *testing.T, kd *KubeDNS, s *v1.Service, portName string) { - records, err := kd.Records(getSRVFQDN(kd, s, portName), false) - require.NoError(t, err) - assert.Equal(t, 1, len(records)) - assert.Equal(t, getServiceFQDN(kd.domain, s), records[0].Host) -} - -func assertNoSRVForNamedPort(t *testing.T, kd *KubeDNS, s *v1.Service, portName string) { - records, err := kd.Records(getSRVFQDN(kd, s, portName), false) - require.Error(t, err) - assert.Equal(t, 0, len(records)) -} - -func assertNoDNSForClusterIP(t *testing.T, kd *KubeDNS, s *v1.Service) { - serviceFQDN := getServiceFQDN(kd.domain, s) - queries := getEquivalentQueries(serviceFQDN, s.Namespace) - for _, query := range queries { - records, err := kd.Records(query, false) - require.Error(t, err) - assert.Equal(t, 0, len(records)) - } -} - -func assertDNSForClusterIP(t *testing.T, kd *KubeDNS, s *v1.Service) { - serviceFQDN := getServiceFQDN(kd.domain, s) - queries := getEquivalentQueries(serviceFQDN, s.Namespace) - for _, query := range queries { - records, err := kd.Records(query, false) - require.NoError(t, err) - assert.Equal(t, 1, len(records)) - assert.Equal(t, s.Spec.ClusterIP, records[0].Host) - } -} - -func assertReverseRecord(t *testing.T, kd *KubeDNS, s *v1.Service) { - segments := util.ReverseArray(strings.Split(s.Spec.ClusterIP, ".")) - reverseLookup := fmt.Sprintf("%s%s", strings.Join(segments, "."), util.ArpaSuffix) - reverseRecord, err := kd.ReverseRecord(reverseLookup) - require.NoError(t, err) - assert.Equal(t, getServiceFQDN(kd.domain, s), reverseRecord.Host) -} - -func assertNoReverseRecord(t *testing.T, kd *KubeDNS, s *v1.Service) { - segments := util.ReverseArray(strings.Split(s.Spec.ClusterIP, ".")) - reverseLookup := fmt.Sprintf("%s%s", strings.Join(segments, "."), util.ArpaSuffix) - reverseRecord, err := kd.ReverseRecord(reverseLookup) - require.Error(t, err) - require.Nil(t, reverseRecord) -} - -func getEquivalentQueries(serviceFQDN, namespace string) []string { - return []string{ - serviceFQDN, - strings.Replace(serviceFQDN, ".svc.", ".*.", 1), - strings.Replace(serviceFQDN, namespace, "*", 1), - strings.Replace(strings.Replace(serviceFQDN, namespace, "*", 1), ".svc.", ".*.", 1), - "*." + serviceFQDN, - } -} - -func getFederationServiceFQDN(kd *KubeDNS, s *v1.Service, federationName string) string { - return fmt.Sprintf("%s.%s.%s.svc.%s", s.Name, s.Namespace, federationName, kd.domain) -} - -func getEndpointsFQDN(kd *KubeDNS, e *v1.Endpoints) string { - return fmt.Sprintf("%s.%s.svc.%s", e.Name, e.Namespace, kd.domain) -} - -func getSRVFQDN(kd *KubeDNS, s *v1.Service, portName string) string { - return fmt.Sprintf("_%s._tcp.%s.%s.svc.%s", portName, s.Name, s.Namespace, kd.domain) -} diff --git a/pkg/dns/doc.go b/pkg/dns/doc.go deleted file mode 100644 index efcdcda175d..00000000000 --- a/pkg/dns/doc.go +++ /dev/null @@ -1,23 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package DNS provides a backend for the skydns DNS server started by the -// kubedns cluster addon. It exposes the 2 interface method: Records and -// ReverseRecord, which skydns invokes according to the DNS queries it -// receives. It serves these records by consulting an in memory tree -// populated with Kubernetes Services and Endpoints received from the Kubernetes -// API server. -package dns // import "k8s.io/kubernetes/pkg/dns" diff --git a/pkg/dns/federation/BUILD b/pkg/dns/federation/BUILD deleted file mode 100644 index d1d71be3fb9..00000000000 --- a/pkg/dns/federation/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["federation.go"], - tags = ["automanaged"], - deps = ["//pkg/util/validation:go_default_library"], -) - -go_test( - name = "go_default_test", - srcs = ["federation_test.go"], - library = ":go_default_library", - tags = ["automanaged"], - deps = ["//vendor:github.com/stretchr/testify/assert"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/dns/federation/federation.go b/pkg/dns/federation/federation.go deleted file mode 100644 index acbb1c4f269..00000000000 --- a/pkg/dns/federation/federation.go +++ /dev/null @@ -1,75 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Fed contains federation specific DNS code. -package fed - -import ( - "errors" - "fmt" - "strings" - - "k8s.io/kubernetes/pkg/util/validation" -) - -var ErrExpectedKeyEqualsValue = errors.New("invalid format, must be key=value") - -// ParseFederationsFlag parses the federations command line flag. The -// flag is a comma-separated list of zero or more "name=label" pairs, -// e.g. "a=b,c=d". -func ParseFederationsFlag(str string, federations map[string]string) error { - if strings.TrimSpace(str) == "" { - return nil - } - - for _, val := range strings.Split(str, ",") { - splits := strings.SplitN(strings.TrimSpace(val), "=", 2) - if len(splits) != 2 { - return ErrExpectedKeyEqualsValue - } - - name := strings.TrimSpace(splits[0]) - domain := strings.TrimSpace(splits[1]) - - if err := ValidateName(name); err != nil { - return err - } - if err := ValidateDomain(domain); err != nil { - return err - } - federations[name] = domain - } - - return nil -} - -// ValidateName checks the validity of a federation name. -func ValidateName(name string) error { - if errs := validation.IsDNS1123Label(name); len(errs) != 0 { - return fmt.Errorf("%q not a valid federation name: %q", name, errs) - } - return nil -} - -// ValidateDomain checks the validity of a federation label. -func ValidateDomain(name string) error { - // The federation domain name need not strictly be domain names, we - // accept valid dns names with subdomain components. - if errs := validation.IsDNS1123Subdomain(name); len(errs) != 0 { - return fmt.Errorf("%q not a valid domain name: %q", name, errs) - } - return nil -} diff --git a/pkg/dns/federation/federation_test.go b/pkg/dns/federation/federation_test.go deleted file mode 100644 index c8ce8de443e..00000000000 --- a/pkg/dns/federation/federation_test.go +++ /dev/null @@ -1,76 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package fed - -import ( - "github.com/stretchr/testify/assert" - - "reflect" - "testing" -) - -func TestParseFederationsFlag(t *testing.T) { - type TestCase struct { - input string - hasError bool - expected map[string]string - } - - for _, testCase := range []TestCase{ - {input: "", expected: make(map[string]string)}, - {input: "a=b", expected: map[string]string{"a": "b"}}, - {input: "a=b,cc=dd", expected: map[string]string{"a": "b", "cc": "dd"}}, - {input: "abc=d.e.f", expected: map[string]string{"abc": "d.e.f"}}, - - {input: "ccdd", hasError: true}, - {input: "a=b,ccdd", hasError: true}, - {input: "-", hasError: true}, - {input: "a.b.c=d.e.f", hasError: true}, - } { - output := make(map[string]string) - err := ParseFederationsFlag(testCase.input, output) - - if !testCase.hasError { - assert.Nil(t, err, "unexpected err", testCase) - assert.True(t, reflect.DeepEqual( - testCase.expected, output), output, testCase) - } else { - assert.NotNil(t, err, testCase) - } - } -} - -func TestValidateName(t *testing.T) { - // More complete testing is done in validation.IsDNS1123Label. These - // tests are to catch issues specific to the implementation of - // kube-dns. - assert.NotNil(t, ValidateName("")) - assert.NotNil(t, ValidateName(".")) - assert.NotNil(t, ValidateName("ab.cd")) - assert.Nil(t, ValidateName("abcd")) -} - -func TestValidateDomain(t *testing.T) { - // More complete testing is done in - // validation.IsDNS1123Subdomain. These tests are to catch issues - // specific to the implementation of kube-dns. - assert.NotNil(t, ValidateDomain("")) - assert.NotNil(t, ValidateDomain(".")) - assert.Nil(t, ValidateDomain("ab.cd")) - assert.Nil(t, ValidateDomain("abcd")) - assert.Nil(t, ValidateDomain("a.b.c.d")) -} diff --git a/pkg/dns/treecache/BUILD b/pkg/dns/treecache/BUILD deleted file mode 100644 index 5e2e4e6d783..00000000000 --- a/pkg/dns/treecache/BUILD +++ /dev/null @@ -1,37 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", - "go_test", -) - -go_library( - name = "go_default_library", - srcs = ["treecache.go"], - tags = ["automanaged"], - deps = ["//vendor:github.com/skynetservices/skydns/msg"], -) - -go_test( - name = "go_default_test", - srcs = ["treecache_test.go"], - library = ":go_default_library", - tags = ["automanaged"], - deps = ["//vendor:github.com/skynetservices/skydns/msg"], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/dns/treecache/treecache.go b/pkg/dns/treecache/treecache.go deleted file mode 100644 index b4ddbfb56d2..00000000000 --- a/pkg/dns/treecache/treecache.go +++ /dev/null @@ -1,213 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package treecache - -import ( - "encoding/json" - "strings" - - skymsg "github.com/skynetservices/skydns/msg" -) - -type TreeCache interface { - // GetEntry with the given key for the given path. - GetEntry(key string, path ...string) (interface{}, bool) - - // Get a list of values including wildcards labels (e.g. "*"). - GetValuesForPathWithWildcards(path ...string) []*skymsg.Service - - // SetEntry creates the entire path if it doesn't already exist in - // the cache, then sets the given service record under the given - // key. The path this entry would have occupied in an etcd datastore - // is computed from the given fqdn and stored as the "Key" of the - // skydns service; this is only required because skydns expects the - // service record to contain a key in a specific format (presumably - // for legacy compatibility). Note that the fqnd string typically - // contains both the key and all elements in the path. - SetEntry(key string, val *skymsg.Service, fqdn string, path ...string) - - // SetSubCache inserts the given subtree under the given - // path:key. Usually the key is the name of a Kubernetes Service, - // and the path maps to the cluster subdomains matching the Service. - SetSubCache(key string, subCache TreeCache, path ...string) - - // DeletePath removes all entries associated with a given path. - DeletePath(path ...string) bool - - // Serialize dumps a JSON representation of the cache. - Serialize() (string, error) -} - -type treeCache struct { - ChildNodes map[string]*treeCache - Entries map[string]interface{} -} - -func NewTreeCache() TreeCache { - return &treeCache{ - ChildNodes: make(map[string]*treeCache), - Entries: make(map[string]interface{}), - } -} - -func (cache *treeCache) Serialize() (string, error) { - prettyJSON, err := json.MarshalIndent(cache, "", "\t") - if err != nil { - return "", err - } - return string(prettyJSON), nil -} - -func (cache *treeCache) SetEntry(key string, val *skymsg.Service, fqdn string, path ...string) { - // TODO: Consolidate setEntry and setSubCache into a single method with a - // type switch. - // TODO: Instead of passing the fqdn as an argument, we can reconstruct - // it from the path, provided callers always pass the full path to the - // object. This is currently *not* the case, since callers first create - // a new, empty node, populate it, then parent it under the right path. - // So we don't know the full key till the final parenting operation. - node := cache.ensureChildNode(path...) - - // This key is used to construct the "target" for SRV record lookups. - // For normal service/endpoint lookups, this will result in a key like: - // /skydns/local/cluster/svc/svcNS/svcName/record-hash - // but for headless services that govern pods requesting a specific - // hostname (as used by petset), this will end up being: - // /skydns/local/cluster/svc/svcNS/svcName/pod-hostname - val.Key = skymsg.Path(fqdn) - node.Entries[key] = val -} - -func (cache *treeCache) getSubCache(path ...string) *treeCache { - childCache := cache - for _, subpath := range path { - childCache = childCache.ChildNodes[subpath] - if childCache == nil { - return nil - } - } - return childCache -} - -func (cache *treeCache) SetSubCache(key string, subCache TreeCache, path ...string) { - node := cache.ensureChildNode(path...) - node.ChildNodes[key] = subCache.(*treeCache) -} - -func (cache *treeCache) GetEntry(key string, path ...string) (interface{}, bool) { - childNode := cache.getSubCache(path...) - if childNode == nil { - return nil, false - } - val, ok := childNode.Entries[key] - return val, ok -} - -func (cache *treeCache) GetValuesForPathWithWildcards(path ...string) []*skymsg.Service { - retval := []*skymsg.Service{} - nodesToExplore := []*treeCache{cache} - for idx, subpath := range path { - nextNodesToExplore := []*treeCache{} - if idx == len(path)-1 { - // if path ends on an entry, instead of a child node, add the entry - for _, node := range nodesToExplore { - if subpath == "*" { - nextNodesToExplore = append(nextNodesToExplore, node) - } else { - if val, ok := node.Entries[subpath]; ok { - retval = append(retval, val.(*skymsg.Service)) - } else { - childNode := node.ChildNodes[subpath] - if childNode != nil { - nextNodesToExplore = append(nextNodesToExplore, childNode) - } - } - } - } - nodesToExplore = nextNodesToExplore - break - } - - if subpath == "*" { - for _, node := range nodesToExplore { - for subkey, subnode := range node.ChildNodes { - if !strings.HasPrefix(subkey, "_") { - nextNodesToExplore = append(nextNodesToExplore, subnode) - } - } - } - } else { - for _, node := range nodesToExplore { - childNode := node.ChildNodes[subpath] - if childNode != nil { - nextNodesToExplore = append(nextNodesToExplore, childNode) - } - } - } - nodesToExplore = nextNodesToExplore - } - - for _, node := range nodesToExplore { - for _, val := range node.Entries { - retval = append(retval, val.(*skymsg.Service)) - } - } - return retval -} - -func (cache *treeCache) DeletePath(path ...string) bool { - if len(path) == 0 { - return false - } - if parentNode := cache.getSubCache(path[:len(path)-1]...); parentNode != nil { - name := path[len(path)-1] - if _, ok := parentNode.ChildNodes[name]; ok { - delete(parentNode.ChildNodes, name) - return true - } - // ExternalName services are stored with their name as the leaf key - if _, ok := parentNode.Entries[name]; ok { - delete(parentNode.Entries, name) - return true - } - } - return false -} - -func (cache *treeCache) appendValues(recursive bool, ref [][]interface{}) { - for _, value := range cache.Entries { - ref[0] = append(ref[0], value) - } - if recursive { - for _, node := range cache.ChildNodes { - node.appendValues(recursive, ref) - } - } -} - -func (cache *treeCache) ensureChildNode(path ...string) *treeCache { - childNode := cache - for _, subpath := range path { - newNode, ok := childNode.ChildNodes[subpath] - if !ok { - newNode = NewTreeCache().(*treeCache) - childNode.ChildNodes[subpath] = newNode - } - childNode = newNode - } - return childNode -} diff --git a/pkg/dns/treecache/treecache_test.go b/pkg/dns/treecache/treecache_test.go deleted file mode 100644 index b6fcbf885f1..00000000000 --- a/pkg/dns/treecache/treecache_test.go +++ /dev/null @@ -1,161 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package treecache - -import ( - "testing" - - "github.com/skynetservices/skydns/msg" -) - -func TestTreeCache(t *testing.T) { - tc := NewTreeCache() - - { - _, ok := tc.GetEntry("key1", "p1", "p2") - if ok { - t.Errorf("key should not exist") - } - } - - checkExists := func(key string, expectedSvc *msg.Service, path ...string) { - svc, ok := tc.GetEntry(key, path...) - if !ok { - t.Fatalf("key %v should exist", key) - } - if svc := svc.(*msg.Service); svc != nil { - if svc != expectedSvc { - t.Errorf("value is not correct (%v != %v)", svc, expectedSvc) - } - } else { - t.Errorf("entry is not of the right type: %T", svc) - } - } - setEntryTC := []struct { - key string - svc *msg.Service - fqdn string - path []string - }{ - {"key1", &msg.Service{}, "key1.p2.p1.", []string{"p1", "p2"}}, - {"key2", &msg.Service{}, "key2.p2.p1.", []string{"p1", "p2"}}, - {"key3", &msg.Service{}, "key3.p2.p1.", []string{"p1", "p3"}}, - } - - for _, testCase := range setEntryTC { - tc.SetEntry(testCase.key, testCase.svc, testCase.fqdn, testCase.path...) - checkExists(testCase.key, testCase.svc, testCase.path...) - } - - wildcardTC := []struct { - path []string - count int - }{ - {[]string{"p1"}, 0}, - {[]string{"p1", "p2"}, 2}, - {[]string{"p1", "p3"}, 1}, - {[]string{"p1", "p2", "key1"}, 1}, - {[]string{"p1", "p2", "key2"}, 1}, - {[]string{"p1", "p2", "key3"}, 0}, - {[]string{"p1", "p3", "key3"}, 1}, - {[]string{"p1", "p2", "*"}, 2}, - {[]string{"p1", "*", "*"}, 3}, - } - - for _, testCase := range wildcardTC { - services := tc.GetValuesForPathWithWildcards(testCase.path...) - if len(services) != testCase.count { - t.Fatalf("Expected %v services for path %v, got %v", - testCase.count, testCase.path, len(services)) - } - } - - // Delete some paths - if !tc.DeletePath("p1", "p2") { - t.Fatal("should delete path p2.p1.") - } - if _, ok := tc.GetEntry("key3", "p1", "p3"); !ok { - t.Error("should not affect p3.p1.") - } - if tc.DeletePath("p1", "p2") { - t.Fatalf("should not be able to delete p2.p1") - } - if !tc.DeletePath("p1", "p3") { - t.Fatalf("should be able to delete p3.p1") - } - if tc.DeletePath("p1", "p3") { - t.Fatalf("should not be able to delete p3.t1") - } - - for _, testCase := range []struct { - k string - p []string - }{ - {"key1", []string{"p1", "p2"}}, - {"key2", []string{"p1", "p2"}}, - {"key3", []string{"p1", "p3"}}, - } { - if _, ok := tc.GetEntry(testCase.k, testCase.p...); ok { - t.Error("path should not exist") - } - } -} - -func TestTreeCacheSetSubCache(t *testing.T) { - tc := NewTreeCache() - - m := &msg.Service{} - - branch := NewTreeCache() - branch.SetEntry("key1", m, "key", "p2") - - tc.SetSubCache("p1", branch, "p0") - - if _, ok := tc.GetEntry("key1", "p0", "p1", "p2"); !ok { - t.Errorf("should be able to get entry p0.p1.p2.key1") - } -} - -func TestTreeCacheSerialize(t *testing.T) { - tc := NewTreeCache() - tc.SetEntry("key1", &msg.Service{}, "key1.p2.p1.", "p1", "p2") - - const expected = `{ - "ChildNodes": { - "p1": { - "ChildNodes": { - "p2": { - "ChildNodes": {}, - "Entries": { - "key1": {} - } - } - }, - "Entries": {} - } - }, - "Entries": {} -}` - - actual, err := tc.Serialize() - if err != nil { - } - - if actual != expected { - t.Errorf("expected %q, got %q", expected, actual) - } -} diff --git a/pkg/dns/util/BUILD b/pkg/dns/util/BUILD deleted file mode 100644 index f56b873d9a2..00000000000 --- a/pkg/dns/util/BUILD +++ /dev/null @@ -1,31 +0,0 @@ -package(default_visibility = ["//visibility:public"]) - -licenses(["notice"]) - -load( - "@io_bazel_rules_go//go:def.bzl", - "go_library", -) - -go_library( - name = "go_default_library", - srcs = ["util.go"], - tags = ["automanaged"], - deps = [ - "//vendor:github.com/golang/glog", - "//vendor:github.com/skynetservices/skydns/msg", - ], -) - -filegroup( - name = "package-srcs", - srcs = glob(["**"]), - tags = ["automanaged"], - visibility = ["//visibility:private"], -) - -filegroup( - name = "all-srcs", - srcs = [":package-srcs"], - tags = ["automanaged"], -) diff --git a/pkg/dns/util/util.go b/pkg/dns/util/util.go deleted file mode 100644 index fc01e6dc4e3..00000000000 --- a/pkg/dns/util/util.go +++ /dev/null @@ -1,89 +0,0 @@ -/* -Copyright 2016 The Kubernetes Authors. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package util - -import ( - "fmt" - "hash/fnv" - "strings" - - "github.com/golang/glog" - "github.com/skynetservices/skydns/msg" -) - -const ( - // ArpaSuffix is the standard suffix for PTR IP reverse lookups. - ArpaSuffix = ".in-addr.arpa." - // defaultPriority used for service records - defaultPriority = 10 - // defaultWeight used for service records - defaultWeight = 10 - // defaultTTL used for service records - defaultTTL = 30 -) - -// extractIP turns a standard PTR reverse record lookup name -// into an IP address -func ExtractIP(reverseName string) (string, bool) { - if !strings.HasSuffix(reverseName, ArpaSuffix) { - return "", false - } - search := strings.TrimSuffix(reverseName, ArpaSuffix) - - // reverse the segments and then combine them - segments := ReverseArray(strings.Split(search, ".")) - return strings.Join(segments, "."), true -} - -// ReverseArray reverses an array. -func ReverseArray(arr []string) []string { - for i := 0; i < len(arr)/2; i++ { - j := len(arr) - i - 1 - arr[i], arr[j] = arr[j], arr[i] - } - return arr -} - -// Returns record in a format that SkyDNS understands. -// Also return the hash of the record. -func GetSkyMsg(ip string, port int) (*msg.Service, string) { - msg := NewServiceRecord(ip, port) - hash := HashServiceRecord(msg) - glog.V(5).Infof("Constructed new DNS record: %s, hash:%s", - fmt.Sprintf("%v", msg), hash) - return msg, fmt.Sprintf("%x", hash) -} - -// NewServiceRecord creates a new service DNS message. -func NewServiceRecord(ip string, port int) *msg.Service { - return &msg.Service{ - Host: ip, - Port: port, - Priority: defaultPriority, - Weight: defaultWeight, - Ttl: defaultTTL, - } -} - -// HashServiceRecord hashes the string representation of a DNS -// message. -func HashServiceRecord(msg *msg.Service) string { - s := fmt.Sprintf("%v", msg) - h := fnv.New32a() - h.Write([]byte(s)) - return fmt.Sprintf("%x", h.Sum32()) -} diff --git a/pkg/generated/bindata.go b/pkg/generated/bindata.go index 5654d3cdc3d..2152a511f4b 100644 --- a/pkg/generated/bindata.go +++ b/pkg/generated/bindata.go @@ -75,7 +75,7 @@ func (fi bindataFileInfo) Sys() interface{} { return nil } -var _translationsKubectlDefaultLc_messagesK8sMo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xbc\x93\xcf\x6e\xd3\x4e\x10\xc7\x27\xbf\xf6\x77\xf1\x91\x33\x87\x41\x02\xa9\x08\x8d\x59\xbb\xa5\xaa\x5c\x82\x50\x4b\x8b\x22\x25\x6a\x54\x5c\xd4\x23\x1b\xef\xd4\x59\xb4\xd9\xb5\x76\xd7\x4d\x7b\xe4\x21\x78\x05\x2e\xf0\x16\xbc\x02\x67\x9e\x05\x39\x86\x14\x6e\xbd\xb4\x7b\xb0\xfc\x1d\x7d\xfc\x9d\x3f\x9e\xfd\xf9\x60\xf3\x33\x00\xc0\x06\x00\x3c\x04\x80\x1d\x00\xf8\x1f\x00\xc6\xd0\x9f\x0f\x00\x30\x02\x00\x09\x00\x5b\x03\x80\xaf\x00\xf0\x6d\x00\xf0\x63\x00\xf0\x18\x00\x3e\x6d\x00\x7c\x07\x80\x2f\x1b\x00\x83\xdf\x3e\x7f\xce\x7f\xdd\xe3\xac\x51\x32\x32\xc6\x39\xa3\xb4\xd6\x45\x19\xb5\xb3\x01\x9d\x45\x89\x9e\x83\x6b\x7d\xc5\x9b\xb7\x81\x60\x29\x63\x35\x47\xdd\x85\xcd\x35\x86\xb6\x69\x9c\x8f\xac\x3a\x4a\x5b\xa5\x2f\xb5\x6a\xa5\x59\xe3\x01\xa5\x55\x6b\x85\x95\x33\x86\xab\xde\x96\xf0\x89\xfa\x8b\x5b\xb2\x67\xbc\x70\xad\x55\x9b\x77\x9f\xe2\x1e\xba\x80\xa9\x77\x1f\xb9\x8a\x34\x52\xf4\x9e\x7d\xd0\xce\x16\x58\x73\x8c\x7c\x15\xa9\x76\xc4\x57\x72\xd1\x18\x0e\x34\x67\x63\x5c\x72\xca\x5d\x05\x34\x09\xb5\x56\x74\xd0\xd6\x81\x4a\x57\x60\x32\x3d\x29\xe9\xd0\xf3\xea\x4f\xd0\x1b\x19\xb9\xc0\x5c\x64\xdb\x94\xe5\x94\xe5\x98\x8b\x42\x6c\x3f\x13\x42\x88\x64\x7a\x42\xa7\x7c\xa9\xc3\x3f\xdc\xee\x8a\xdb\xc6\x3c\x2b\x5e\xec\x90\xd8\x13\x22\x19\xcb\x10\xa9\xf4\xd2\x06\x23\xa3\xf3\x05\x1e\x78\xb6\x4a\x5a\x3c\x68\xbd\x0d\xf8\x72\xd6\xcb\x54\xa5\xb3\x2e\xf0\xba\x5e\x48\x6d\xd2\xca\x2d\x5e\x25\x93\xd1\xe4\xe8\xa6\x95\x2c\x15\xc9\xa1\xb3\x91\x6d\xa4\xf2\xba\xe1\x02\xbb\xce\x9e\x37\x46\x6a\xbb\x8f\xd5\x5c\xfa\xc0\x71\x78\x56\x1e\xd3\xde\x0d\xd7\xe5\xbd\x60\x4f\x47\xb6\x72\x4a\xdb\xba\xc0\xbd\x99\x8e\xc9\x39\xbd\x65\xcb\xbe\x2f\x68\xea\x58\xe9\x88\x59\xba\x9b\x66\x22\x39\xa7\x5e\xd3\xbb\xd5\x84\x0f\x7b\xdf\x02\x7b\xe3\xb1\xb4\x75\x2b\x6b\xa6\x92\xe5\xa2\x1b\x97\x69\xbd\x34\x74\xec\xfc\x22\x14\x68\x9b\x95\x0c\xc3\x7c\x1f\xfb\xd7\xe1\x96\xc5\x47\x43\xcc\x9e\xee\xaf\x3f\x2d\x90\x6d\x72\xab\xfb\x71\x47\x4b\x83\x4b\x19\xee\x6f\x2b\x7f\x05\x00\x00\xff\xff\xaa\xa3\x15\xc3\x6a\x04\x00\x00") +var _translationsKubectlDefaultLc_messagesK8sMo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xbc\x53\xc1\x6e\xd3\x40\x10\x75\x21\x5c\x7c\xe4\xcc\x61\x90\x40\x2a\x42\x13\xec\xa4\x54\x91\x43\x10\x4a\x68\x51\xa4\x44\x44\x25\x45\x1c\xd9\x78\xa7\xce\xa2\xf5\xae\xb5\xbb\x6e\xda\x23\x1f\xc1\x2f\x70\x81\xbf\xe0\x17\x38\xf3\x2d\x8c\x63\x48\xe1\xd6\x4b\x3b\xf2\xf3\xcc\xac\xdf\xbe\xd9\xd9\x5d\xff\xba\xdf\xf9\x12\xb1\xdd\x65\x3c\x60\x1c\x30\xee\x31\x66\x51\x6b\x1f\x19\x53\x86\x60\xec\xef\x45\xd1\x37\xf6\xdf\xd9\xff\x64\x3c\xe2\xf8\x33\x4f\xfc\xc1\xfe\x2b\xfb\xbd\x3f\x3a\x7f\xed\x4e\xf3\x3a\xad\xa4\x08\x04\x61\x4d\x20\x8c\xb1\x41\x04\x65\x8d\x07\x6b\x40\x80\x23\x6f\x6b\x97\x53\xe7\x3a\xa4\x68\x23\x42\xbe\x06\xd5\x0c\xeb\x4b\xf0\x75\x55\x59\x17\x48\x36\x2c\x65\xa4\x3a\x57\xb2\x16\x7a\x47\xf7\xac\x24\x77\x19\xe4\x56\x6b\xca\x5b\x59\x84\xc7\xf2\x1f\xde\x86\x1c\xc1\x99\xad\x8d\xec\xdc\x7c\x89\x5b\xe8\x22\x5a\x38\xfb\x89\x59\x38\x95\xf8\x9e\x9c\x67\x76\x06\x05\x85\x40\x17\x01\x0b\x8b\x74\x21\xca\x4a\x93\xc7\x35\x69\x6d\xe3\x13\x6a\x56\x80\x73\x5f\x28\x89\xe3\xba\xf0\xb8\xb4\x19\xc4\x8b\xb7\x4b\x9c\x38\xda\x9e\x04\xbe\xe6\xd3\xc9\xa0\x97\xa4\x7d\x4c\x7b\xfc\x70\x98\x25\xfd\xa7\x09\x1b\x13\xf1\x84\xce\x95\xff\x8f\x77\xb8\xe5\xf5\xa1\x97\x66\xcf\x0f\x30\x19\x30\x6f\x26\x7c\xc0\xa5\x13\xc6\x6b\x11\xac\xcb\x60\xec\xc8\x48\x61\x60\x5c\x3b\x6e\xe7\xc5\xaa\x4d\xbb\xb2\xbb\x6a\x06\x5e\x15\xa5\x50\xba\x9b\xdb\xf2\x65\x3c\x9f\xce\x8f\xae\x5a\x49\xbb\x49\x3c\xb1\x26\x90\x61\xbd\xcb\x8a\x0b\x36\x9d\x3d\xab\xb4\x50\x66\x08\xf9\x5a\x38\x4f\x61\x74\xba\x3c\xc6\xc1\x15\xaf\xa9\x7b\x46\x0e\x8f\x4c\x6e\xa5\x32\x45\x06\x83\x95\x0a\xf1\x07\x7c\x43\x86\x5c\xbb\xa0\x85\x25\xa9\x02\xeb\x1f\x76\xd3\x84\x3f\xb5\x39\xbe\xdb\xee\xf0\xa4\xd5\xcd\xa0\x15\x9e\x09\x53\xd4\xa2\x20\x5c\x92\x28\x9b\xed\xd2\xb5\x13\x1a\x8f\xad\x2b\x7d\x06\xa6\xda\xa6\x7e\xd4\x1b\x42\x1b\x8e\xf6\x0d\x3c\x1c\x41\xfa\x64\xb8\x9b\x9a\x01\x99\xf8\x5a\xff\xc7\x0d\x5d\x1a\xd8\x08\x7f\x7b\xb7\xf2\x77\x00\x00\x00\xff\xff\xaa\xa3\x15\xc3\x6a\x04\x00\x00") func translationsKubectlDefaultLc_messagesK8sMoBytes() ([]byte, error) { return bindataRead( @@ -95,7 +95,7 @@ func translationsKubectlDefaultLc_messagesK8sMo() (*asset, error) { return a, nil } -var _translationsKubectlDefaultLc_messagesK8sPo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xbc\x53\xdd\x6e\xd3\x4c\x10\xbd\xcf\x53\xcc\xe7\xe8\x93\x5a\xc1\x1a\x3b\x85\xaa\x72\x09\xa2\x0d\x6d\xa9\x68\xd5\x28\x75\x11\x12\x20\xb4\xf1\x4e\x9c\x85\xf5\xac\xb5\x33\xee\xcf\xdb\x23\xdb\x69\x43\x90\x90\x7a\xd3\xde\xcd\xce\x9e\x99\x33\x67\xf6\xec\x10\x72\x64\x01\x09\x9a\xd8\x69\xb1\x9e\x18\x16\x3e\x40\x43\x56\x40\x90\x85\xe3\xc1\x10\x26\xbe\xbe\x0b\xb6\x5c\x0a\x6c\x4d\xb6\x61\x94\xa4\xbb\x83\x21\xe4\x4b\xcb\xb0\xb0\x0e\xc1\x32\x18\xcb\x12\xec\xbc\x11\x34\xd0\x90\xc1\x00\xb2\x44\x60\x5d\x21\x38\x5b\x20\x31\x82\xe6\x2e\x37\x3d\x98\x7c\x3a\x38\x39\x82\x5a\x17\xbf\x74\x89\x6d\xfb\xe3\xd3\xd9\x65\x0e\x07\x57\xf9\xc7\x8b\x19\xcc\x03\x92\xd1\x14\x9b\x78\xde\x04\xe2\xf7\x65\xa5\xad\x8b\x0b\x5f\xbd\xec\x88\xe3\xc1\x70\x50\x71\x69\x0d\x44\x51\x1b\xb0\x84\x36\x8a\xa6\xc1\xff\xc4\x42\xd4\xa9\x51\x9f\x31\xb0\xf5\x94\x41\x89\x22\x78\x2b\xaa\xf4\x0a\x6f\x75\x55\x3b\x64\xb5\x44\xe7\xfc\x37\x8a\x06\xd1\x0c\x6b\x1f\x44\x9d\xb7\xcd\xd4\x61\x53\xb2\xca\x7d\x06\xdd\xd5\xf4\x22\x57\x93\x80\xdd\x3e\xd4\x07\x2d\x98\xb5\xdc\x3b\x2a\x1d\xa9\x74\x04\xa3\x24\x4b\x76\x5e\x24\x49\x92\xac\xc0\x6a\x86\xd7\x96\x37\xb0\xbb\x1d\x76\x07\x46\x69\xf6\xe6\xb5\x4a\xf6\x56\xd8\x33\xcd\xa2\xf2\xd5\xb2\x7d\xc8\xe0\xb0\x57\x0b\x87\xad\x56\x78\xfb\x4f\xf1\xef\xba\xf2\xf3\xd3\xf3\xa3\xb5\xbc\x34\xee\x9b\x4e\x3c\x09\x92\xa8\xfc\xae\xc6\x0c\x5a\xc5\xaf\x6a\xa7\x2d\xed\x43\xb1\xd4\x81\x51\xc6\x57\xf9\xb1\xda\xdb\xc4\xb6\x33\x2c\x30\xa8\x23\x2a\xbc\xb1\x54\x66\xb0\x37\xb7\xd2\x61\xbe\xa8\x13\x24\x0c\xfd\x80\x53\x8f\xc6\x0a\xa4\xf1\x6e\x9c\x26\xab\xeb\x3e\xa7\x2e\x7d\x13\x0a\x9c\xf4\x1c\x19\xac\x49\xce\x34\x95\x8d\x2e\x51\xe5\xa8\xab\xfb\x95\xba\x26\x68\xa7\x8e\x7d\xa8\x38\x03\xaa\xbb\x23\x8f\x47\xfb\xd0\x87\xe3\x2d\x82\xff\xc6\x90\x6e\xef\x6f\xb4\xc8\x00\xa9\x4d\xb4\x4f\x5d\xc8\xad\x40\x74\x55\x1b\x2d\xd8\x59\x49\x13\x79\x59\x99\xd6\x13\x68\x08\xc8\xdd\x4c\xd1\xbd\x45\x1e\x0d\xee\x6c\xf4\x38\xf4\x7a\x94\x68\x10\xdd\x68\x29\x96\xed\x07\xf0\xe4\xee\x80\x9b\xba\xf5\x14\x9a\xb6\xc6\x92\xb1\xd7\xd6\x34\xda\x3d\x14\x33\x68\x32\x0f\x27\x28\xbc\x73\x58\xf4\x24\x0a\xa2\x41\xf4\xbf\xf9\x03\x7a\x83\x01\x61\xe1\x1b\x32\xd1\xda\xf1\xcf\x4a\xf8\xa3\x7f\x9a\x67\xe6\x65\x09\x5f\x93\xef\x4f\x4b\x0a\x37\x9a\xff\xa2\x4c\x9f\x98\x72\x53\xe7\xef\x00\x00\x00\xff\xff\x96\x33\xff\xe8\x78\x05\x00\x00") +var _translationsKubectlDefaultLc_messagesK8sPo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xbc\x53\x6f\x4f\xdb\x3e\x10\x7e\xcf\xa7\xb8\x5f\xd1\x4f\x02\x6d\xce\x92\xb2\x21\x14\xd6\x69\x90\x01\x43\x03\x51\x95\x30\x4d\xda\xa6\xc9\x8d\x8f\xc4\x9b\x63\x47\xb6\x03\xf4\xdb\xef\xec\x14\xba\x4e\x9a\xc4\x1b\xa8\x2a\xc5\x3e\x3f\x77\xcf\xfd\x79\x6e\x13\x4a\x74\x1e\xbc\xe5\xda\x29\xee\xa5\xd1\x0e\xae\x8d\x85\x5e\x4b\xb2\xd2\x93\x4b\x36\x36\xa1\x30\xdd\xc2\xca\xba\xf1\xb0\x55\x6c\xc3\x38\xcd\x76\xc9\x58\x36\x92\xb0\x52\x21\xd0\x57\x48\xe7\xad\x9c\xf7\x1e\x05\xf9\x0a\xb4\xe0\x1b\x04\xc7\x5b\x04\x25\x2b\xd4\x0e\x81\xbb\x68\x9b\x1e\x14\x9f\x0e\x4e\x8e\xa0\xe3\xd5\x2f\x5e\x63\x08\x7f\x7c\x3a\xbb\x2c\xe1\xe0\xaa\xfc\x78\x31\x83\xb9\x45\x2d\xb8\x4e\x44\x32\xef\xad\x76\xef\xeb\x96\x4b\x95\x54\xa6\x7d\x19\x89\x09\xbf\xd1\xba\x5a\x0a\x18\x8d\xc2\x81\x68\xc3\x69\x34\xb5\xe6\x27\x56\x9e\x9d\x0a\xf6\x19\xad\xa3\x42\x72\xa8\xd1\x7b\xbc\xf3\xac\x36\x0c\xef\x78\xdb\x29\x74\xac\x41\xa5\xcc\x37\x4d\x1e\x33\xec\x8c\xf5\xec\x3c\x04\x63\x87\x7d\xed\x58\x69\x72\x88\x4f\xd3\x8b\x92\x15\x16\x63\x3f\xd8\x07\xee\x31\x0f\xdc\x3b\x2c\x1b\xd3\x9f\x8e\x79\xba\xf3\x22\xa5\xdf\x12\xcc\x66\x78\x23\xdd\x1a\x76\x37\x62\x77\x60\x9c\xe5\x6f\x5e\xb3\x74\x6f\x89\x3d\xe3\xce\xb3\x72\xd9\x6c\x63\x73\x38\x1c\xaa\x85\xc3\x50\x2b\xbc\xfd\x67\xf1\xef\xa2\xfb\xf9\xe9\xf9\xd1\xaa\xbc\x2c\x19\x82\x16\x46\x7b\xd4\x14\x77\xd1\x11\x79\xa8\xf8\x55\xa7\xb8\xd4\xfb\x50\x35\xdc\x3a\xf4\x93\xab\xf2\x98\xed\xad\x63\x43\x0e\xd7\x68\xd9\x91\xae\x8c\x90\xba\xce\x61\x6f\x2e\x7d\xc4\x7c\x61\x27\xa8\xd1\x0e\x09\x4e\x0d\x0a\x92\x42\x96\xec\x26\x59\xba\x7c\x1e\x6c\xec\xd2\xf4\xb6\xc2\x62\xe0\xc8\x61\x45\x72\xc6\x75\xdd\xd3\x6c\x59\x89\xbc\xbd\x6f\xa9\xea\x2d\x57\xec\xd8\xd8\xd6\xe5\xa0\xbb\x78\x75\x93\xf1\x3e\x0c\xc7\xc9\x96\x86\xff\x26\x90\x6d\xef\xaf\x85\xc8\x01\x75\x30\x84\x51\x57\xfe\xce\xc3\xe8\xaa\x13\xd4\xe4\x28\x25\xae\xb5\xf1\x4b\xd1\x1a\x0d\x1c\x2c\xba\x98\xd3\xe8\x5e\x22\x8f\x06\x47\x19\x3d\x0e\xbd\x4a\x85\xf2\xbc\xe5\xbe\x6a\xc2\x02\x18\xad\x16\xe0\xfa\x2e\x68\x8a\x76\x80\x7c\xa4\x16\xf2\x46\x8a\x9e\xab\x07\x67\x47\x71\xc5\xc3\x0d\x2a\xa3\x14\x69\x36\x92\x30\xa0\x68\xff\x8b\x3f\xa0\xb7\x68\x91\x76\x91\xb6\x69\xb4\x52\xfc\xb3\x12\xfe\x18\x46\xf3\xcc\xbc\x34\x8a\xaf\xe9\xf7\xa7\x25\x85\x5b\xee\xfe\xa2\xcc\x9e\x98\x72\xbd\xce\xdf\x01\x00\x00\xff\xff\x96\x33\xff\xe8\x78\x05\x00\x00") func translationsKubectlDefaultLc_messagesK8sPoBytes() ([]byte, error) { return bindataRead( @@ -115,7 +115,7 @@ func translationsKubectlDefaultLc_messagesK8sPo() (*asset, error) { return a, nil } -var _translationsKubectlEn_usLc_messagesK8sMo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xbc\x93\xcf\x6e\xd3\x40\x10\xc6\x27\xb4\x5c\x7c\xe4\xcc\x61\x90\x40\x2a\x42\x63\xd6\x0e\x54\x95\x4b\x10\x6a\x69\x51\xa5\x44\x8d\x8a\x8b\x7a\x64\xe3\x9d\x3a\x8b\x36\xbb\xd6\xee\xba\x69\x8f\x3c\x04\xaf\xc0\x05\xde\x82\x57\xe0\xcc\xb3\x20\xc7\x90\xc2\xad\x97\x76\x0f\x96\xbf\xd1\xcf\xdf\xfc\xf1\xec\xaf\x07\x9b\x5f\x00\x00\x36\x00\xe0\x21\x00\xbc\x00\x80\xfb\x00\x30\x86\xfe\x7c\x04\x80\x23\x00\x90\x00\xb0\x35\x00\xf8\x06\x00\xdf\x07\x00\x3f\x07\x00\x8f\x01\xe0\xf3\x06\xc0\x0f\x00\xf8\xba\x01\x30\xf8\xe3\xf3\xf7\xdc\xeb\x1e\xa7\x8d\x92\x91\x31\xce\x19\xa5\xb5\x2e\xca\xa8\x9d\x0d\xe8\x2c\x4a\xf4\x1c\x5c\xeb\x2b\xde\xbc\x09\x04\x4b\x19\xab\x39\xea\x2e\x6c\xae\x30\xb4\x4d\xe3\x7c\x64\xd5\x51\xda\x2a\x7d\xa1\x55\x2b\xcd\x1a\x0f\x28\xad\x5a\x2b\xac\x9c\x31\x5c\xf5\xb6\x84\x4f\xd4\x3f\xdc\x92\x3d\xe3\xb9\x6b\xad\xda\xbc\xfd\x14\x77\xd0\x05\x4c\xbd\xfb\xc4\x55\xa4\x23\x45\x1f\xd8\x07\xed\x6c\x81\x35\xc7\xc8\x97\x91\x6a\x47\x7c\x29\x17\x8d\xe1\x40\x73\x36\xc6\x25\x27\xdc\x55\x40\x93\x50\x6b\x45\x7b\x6d\x1d\xa8\x74\x05\x26\xd3\xe3\x92\xf6\x3d\xaf\xfe\x04\xbd\x95\x91\x0b\xcc\x45\x36\xa4\x2c\xa7\x2c\xc7\x5c\x14\x62\xf8\x4c\x08\x21\x92\xe9\x31\x9d\xf0\x85\x0e\xff\x71\xdb\x2b\x6e\x88\x79\x5e\x0c\x5f\x92\xd8\x11\x22\x19\xcb\x10\xa9\xf4\xd2\x06\x23\xa3\xf3\x05\xee\x79\xb6\x4a\x5a\xdc\x6b\xbd\x0d\xf8\x6a\xd6\xcb\x54\xa5\xb3\x2e\xf0\xa6\x5e\x48\x6d\xd2\xca\x2d\x5e\x27\x93\xa3\xc9\xc1\x75\x2b\x59\x2a\x92\x7d\x67\x23\xdb\x48\xe5\x55\xc3\x05\x76\x9d\x3d\x6f\x8c\xd4\x76\x17\xab\xb9\xf4\x81\xe3\xe8\xb4\x3c\xa4\x9d\x6b\xae\xcb\x7b\xce\x9e\x0e\x6c\xe5\x94\xb6\x75\x81\x3b\x33\x1d\x93\x33\x7a\xc7\x96\x7d\x5f\xd0\xd4\xb1\xd2\x11\xb3\x74\x3b\xcd\x44\x72\x46\xbd\xa6\xf7\xab\x09\xef\xf7\xbe\x05\xf6\xc6\x63\x69\xeb\x56\xd6\x4c\x25\xcb\x45\x37\x2e\xd3\x7a\x69\xe8\xd0\xf9\x45\x28\xd0\x36\x2b\x19\x46\xf9\x2e\xf6\xaf\xa3\x2d\x8b\x8f\x46\x98\x3d\xdd\x5d\x7f\x5a\x20\xdb\xe4\x46\xf7\xe3\x96\x96\x06\x97\x32\xdc\xdd\x56\xfe\x0e\x00\x00\xff\xff\x52\x15\x0d\x38\x6a\x04\x00\x00") +var _translationsKubectlEn_usLc_messagesK8sMo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xbc\x53\xc1\x6e\x13\x31\x10\xdd\x42\xb8\xec\x91\x33\x87\x41\x02\xa9\x08\x4d\xd8\x24\x50\x45\x0e\x41\x28\xa1\x45\x91\x12\x11\x95\x14\x71\xc4\x59\x4f\x37\x46\x8e\xbd\xb2\xbd\x4d\x7b\xe4\x23\xf8\x05\x2e\xf0\x17\xfc\x02\x67\xbe\x85\xd9\x2c\xa4\xf4\xd6\x4b\x3b\xda\xb7\x33\xe3\x7d\x7e\xe3\xb1\xbd\xbf\xef\xb7\xbe\x26\x6c\x77\x19\x0f\x18\xcf\x19\xf7\x18\xd3\xa4\xb1\x4f\x8c\x09\x43\x32\xf6\xf7\x92\xe4\x3b\xfb\x1f\xec\x7f\x31\x1e\x71\xfc\x85\x27\xfe\x64\xff\x8d\xfd\xde\x5f\x9d\x7f\x76\xa7\x7e\x9d\x94\x4a\x46\x82\xb8\x22\x90\xd6\xba\x28\xa3\x76\x36\x80\xb3\x20\xc1\x53\x70\x95\xcf\xa9\x75\x1d\x52\xb2\x91\x31\x5f\x81\xae\x87\xcd\x05\x84\xaa\x2c\x9d\x8f\xa4\x6a\x96\xb6\x4a\x9f\x69\x55\x49\xb3\xa3\x07\x56\x52\xbb\x0c\x72\x67\x0c\xe5\x8d\x2c\xc2\x63\xf5\x1f\x6f\x43\x9e\xe0\xd4\x55\x56\xb5\x6e\xbe\xc4\x2d\x74\x91\xcc\xbd\xfb\xcc\x2c\x9c\x28\xfc\x40\x3e\x30\x5b\x40\x41\x31\xd2\x79\xc4\xc2\x21\x9d\xcb\x75\x69\x28\xe0\x8a\x8c\x71\xe9\x31\xd5\x2b\xc0\x59\x28\xb4\xc2\x51\x55\x04\x5c\x38\x01\xe9\xfc\xdd\x02\xc7\x9e\xb6\x27\x81\x6f\xf8\x74\x04\x74\xb3\x4e\x0f\x3b\x5d\x7e\x38\x14\x59\xef\x69\xc6\xc6\x44\x3c\xa6\x33\x1d\xae\xf0\x0e\xb6\xbc\x1e\x74\xbb\xa2\xf7\x02\xb3\x3e\xf3\xa6\x32\x44\x5c\x78\x69\x83\x91\xd1\x79\x01\x23\x4f\x56\x49\x0b\xa3\xca\x73\x3b\x2f\x97\x4d\xda\x56\xed\x65\x3d\xf0\xba\x58\x4b\x6d\xda\xb9\x5b\xbf\x4a\x67\x93\xd9\xe1\x65\x2b\x9d\x76\x96\x8e\x9d\x8d\x64\x59\xef\xa2\xe4\x82\x75\x67\xcf\x4a\x23\xb5\x1d\x40\xbe\x92\x3e\x50\x1c\x9e\x2c\x8e\xb0\x7f\xc9\xab\xeb\x9e\x92\xc7\x43\x9b\x3b\xa5\x6d\x21\xa0\xbf\xd4\x31\xfd\x88\x6f\xc9\x92\x6f\x16\x34\x77\xa4\x74\x64\xfd\x83\x76\x27\xe3\x4f\x4d\x8e\xef\xb7\x3b\x3c\x6e\x74\x05\x34\xc2\x53\x69\x8b\x4a\x16\x84\x0b\x92\xeb\x7a\xbb\x4c\xe5\xa5\xc1\x23\xe7\xd7\x41\x80\x2d\xb7\x69\x18\x76\x07\xd0\x84\xc3\x7d\x0b\x0f\x87\xd0\x79\x32\xd8\x4d\x15\x40\x36\xbd\xd6\xff\x71\x43\x97\x06\x36\x32\xdc\xde\xad\xfc\x13\x00\x00\xff\xff\x52\x15\x0d\x38\x6a\x04\x00\x00") func translationsKubectlEn_usLc_messagesK8sMoBytes() ([]byte, error) { return bindataRead( @@ -135,7 +135,7 @@ func translationsKubectlEn_usLc_messagesK8sMo() (*asset, error) { return a, nil } -var _translationsKubectlEn_usLc_messagesK8sPo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xbc\x53\x5d\x4f\xdb\x4a\x10\x7d\xcf\xaf\x98\xeb\xe8\x4a\xa0\x7b\xd7\xb5\x13\x15\x21\xd3\x54\x85\x14\x28\x2a\x88\x28\x98\xaa\x52\x5b\x55\x1b\xef\xc4\xd9\x76\x3d\x6b\xed\x8c\xf9\xf8\xf7\x95\xed\x40\x9a\x4a\x95\x78\x81\xb7\xd9\xd9\x33\x73\xe6\xcc\x9e\x1d\x42\x8e\x2c\x20\x41\x13\x3b\x2d\xd6\x13\xc3\xd2\x07\x68\xc8\x0a\x08\xb2\x70\x3c\x18\xc2\xd4\xd7\xf7\xc1\x96\x2b\x81\x9d\xe9\x2e\x8c\x92\x74\x6f\x30\x84\x7c\x65\x19\x96\xd6\x21\x58\x06\x63\x59\x82\x5d\x34\x82\x06\x1a\x32\x18\x40\x56\x08\xac\x2b\x04\x67\x0b\x24\x46\xd0\xdc\xe5\x66\x87\xd3\x8f\x87\xa7\xc7\x50\xeb\xe2\xa7\x2e\xb1\x6d\x7f\x72\x36\xbf\xca\xe1\xf0\x3a\xff\x70\x39\x87\x45\x40\x32\x9a\x62\x13\x2f\x9a\x40\xfc\xae\xac\xb4\x75\x71\xe1\xab\xff\x3b\xe2\x78\x30\x1c\x54\x5c\x5a\x03\x51\xd4\x06\x2c\xa1\x8d\xa2\x59\xf0\x3f\xb0\x10\x75\x66\xd4\x27\x0c\x6c\x3d\x65\x50\xa2\x08\xde\x89\x2a\xbd\xc2\x3b\x5d\xd5\x0e\x59\xad\xd0\x39\xff\x95\xa2\x41\x34\xc7\xda\x07\x51\x17\x6d\x33\x75\xd4\x94\xac\x72\x9f\x41\x77\x35\xbb\xcc\xd5\x34\x60\xb7\x0f\xf5\x5e\x0b\x66\x2d\xf7\x58\xa5\x23\x95\x8e\x60\x94\x64\xc9\xf8\xbf\x24\x49\x92\x35\x58\xcd\xf1\xc6\xf2\x16\x76\xaf\xc3\x8e\x61\x34\xca\xc6\xaf\x55\xb2\xbf\xc6\x9e\x6b\x16\x95\xaf\x97\xed\x43\x06\x47\xbd\x5a\x38\x6a\xb5\xc2\x9b\xbf\x8a\x7f\xdb\x95\x5f\x9c\x5d\x1c\x6f\xe4\xa5\x71\xdf\x74\xea\x49\x90\x44\xe5\xf7\x35\x66\xd0\x2a\x7e\x55\x3b\x6d\xe9\x00\x8a\x95\x0e\x8c\x32\xb9\xce\x4f\xd4\xfe\x36\xb6\x9d\x61\x89\x41\x1d\x53\xe1\x8d\xa5\x32\x83\xfd\x85\x95\x0e\xf3\x59\x9d\x22\x61\xe8\x07\x9c\x79\x34\x56\x20\x8d\xf7\xe2\x34\x59\x5f\xf7\x39\x75\xe5\x9b\x50\xe0\xb4\xe7\xc8\x60\x43\x72\xae\xa9\x6c\x74\x89\x2a\x47\x5d\x3d\xac\xd4\x35\x41\x3b\x75\xe2\x43\xc5\x19\x50\xdd\x1d\x79\x32\x3a\x80\x3e\x9c\xec\x10\xfc\x33\x81\x74\xf7\x60\xab\x45\x06\x48\x6d\xa2\x7d\xea\x42\xee\x04\xa2\xeb\xda\x68\xc1\xce\x4a\x9a\xc8\xcb\xda\xb4\x9e\x40\x43\x40\xee\x66\x8a\x1e\x2c\xf2\x64\x70\x67\xa3\xa7\xa1\x37\xa3\x44\x83\xe8\x56\x4b\xb1\x6a\x3f\x80\x27\x77\x0f\xdc\xd4\xad\xa7\xd0\xb4\x35\x96\x8c\xbd\xb1\xa6\xd1\xee\xb1\x98\x41\x93\x79\x3c\x41\xe1\x9d\xc3\xa2\x27\x51\x10\x0d\xa2\x7f\xcd\x6f\xd0\x5b\x0c\x08\x4b\xdf\x90\x89\x36\x8e\x7f\x51\xc2\xef\xfd\xd3\xbc\x30\x2f\x4b\xf8\x92\x7c\x7b\x5e\x52\xb8\xd5\xfc\x07\x65\xfa\xcc\x94\xdb\x3a\x7f\x05\x00\x00\xff\xff\x61\x66\xb9\x11\x78\x05\x00\x00") +var _translationsKubectlEn_usLc_messagesK8sPo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\xbc\x53\x6d\x4f\xdb\x30\x10\xfe\xce\xaf\xb8\x15\x4d\x02\x6d\xce\x92\x56\x43\x28\xac\xd3\x20\x03\x86\x06\xa2\x2a\x61\x9a\xb4\x4d\x93\x1b\x1f\x89\x37\xc7\x8e\x6c\x87\x97\x7f\xbf\xb3\x53\xe8\x3a\x69\x12\x5f\xa0\xaa\x14\xfb\xfc\xdc\x3d\xf7\xf2\xdc\x26\x94\xe8\x3c\x78\xcb\xb5\x53\xdc\x4b\xa3\x1d\x5c\x19\x0b\xbd\x96\x64\xa5\x27\x97\x6c\x6c\x42\x61\xba\x3b\x2b\xeb\xc6\xc3\x56\xb1\x0d\xe3\x34\xdb\x21\x63\xd9\x48\xc2\x4a\x85\x40\x5f\x21\x9d\xb7\x72\xd1\x7b\x14\xe4\x2b\xd0\x82\x6f\x10\x1c\x6f\x11\x94\xac\x50\x3b\x04\xee\xa2\x6d\xb6\x5f\x7c\xde\x3f\x3e\x84\x8e\x57\xbf\x79\x8d\x21\xfc\xd1\xc9\xfc\xa2\x84\xfd\xcb\xf2\xd3\xf9\x1c\x16\x16\xb5\xe0\x3a\x11\xc9\xa2\xb7\xda\x7d\xa8\x5b\x2e\x55\x52\x99\xf6\x75\x24\x26\xfc\x46\xeb\x6a\x29\x60\x34\x0a\x07\xa2\x0d\xa7\xd1\xcc\x9a\x5f\x58\x79\x76\x22\xd8\x17\xb4\x8e\x0a\xc9\xa1\x46\xef\xf1\xd6\xb3\xda\x30\xbc\xe5\x6d\xa7\xd0\xb1\x06\x95\x32\xdf\x35\x79\xcc\xb1\x33\xd6\xb3\xb3\x10\x8c\x1d\xf4\xb5\x63\xa5\xc9\x21\x3e\xcd\xce\x4b\x56\x58\x8c\xfd\x60\x1f\xb9\xc7\x3c\x70\x4f\x58\x36\xa6\x3f\x1d\xf3\x74\xf2\x2a\xa5\xdf\x12\xcc\xe6\x78\x2d\xdd\x1a\x76\x27\x62\x27\x30\x1e\xe7\x93\xb7\x2c\xdd\x5d\x62\x4f\xb9\xf3\xac\x5c\x36\xdb\xd8\x1c\x0e\x86\x6a\xe1\x20\xd4\x0a\xef\xfe\x5b\xfc\xfb\xe8\x7e\x76\x72\x76\xb8\x2a\x2f\x4b\x86\xa0\x85\xd1\x1e\x35\xc5\xbd\xeb\x88\x3c\x54\xfc\xa6\x53\x5c\xea\x3d\xa8\x1a\x6e\x1d\xfa\xe9\x65\x79\xc4\x76\xd7\xb1\x21\x87\x2b\xb4\xec\x50\x57\x46\x48\x5d\xe7\xb0\xbb\x90\x3e\x62\xbe\xb2\x63\xd4\x68\x87\x04\x67\x06\x05\x49\x21\x4b\x76\x92\x2c\x5d\x3e\x0f\x36\x76\x61\x7a\x5b\x61\x31\x70\xe4\xb0\x22\x39\xe5\xba\xee\x69\xb6\xac\x44\xde\xde\xb7\x54\xf5\x96\x2b\x76\x64\x6c\xeb\x72\xd0\x5d\xbc\xba\xe9\x78\x0f\x86\xe3\x74\x4b\xc3\x8b\x29\x64\xdb\x7b\x6b\x21\x72\x40\x1d\x0c\x61\xd4\x95\xbf\xf5\x30\xba\xec\x04\x35\x39\x4a\x89\x6b\x6d\xfc\x52\xb4\x46\x03\x07\x8b\x2e\xe6\x34\xba\x97\xc8\xa3\xc1\x51\x46\x8f\x43\xaf\x52\xa1\x3c\x6f\xb8\xaf\x9a\xb0\x00\x46\xab\x3b\x70\x7d\x17\x34\x45\x3b\x40\x3e\x52\x0b\x79\x2d\x45\xcf\xd5\x83\xb3\xa3\xb8\xe2\xe1\x06\x95\x51\x8a\x34\x1b\x49\x18\x50\xb4\x97\xe2\x2f\xe8\x0d\x5a\xa4\x5d\xa4\x6d\x1a\xad\x14\xff\xac\x84\x3f\x87\xd1\x3c\x33\x2f\x8d\xe2\x5b\xfa\xe3\x69\x49\xe1\x86\xbb\x7f\x28\xb3\x27\xa6\x5c\xaf\xf3\x4f\x00\x00\x00\xff\xff\x61\x66\xb9\x11\x78\x05\x00\x00") func translationsKubectlEn_usLc_messagesK8sPoBytes() ([]byte, error) { return bindataRead( @@ -155,7 +155,7 @@ func translationsKubectlEn_usLc_messagesK8sPo() (*asset, error) { return a, nil } -var _translationsTestDefaultLc_messagesK8sMo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x64\x51\xc1\x6e\x13\x31\x10\x7d\x0d\xe1\xb2\x47\x2e\x5c\x38\x18\xa1\x4a\x20\x34\x8b\x77\x03\x55\xe4\x10\x84\x12\x5a\x54\x94\xa8\x51\x59\x50\x6f\xe0\x64\xa7\x1b\xa3\x5d\x7b\x65\x3b\x50\x3e\x80\x4f\xe0\xc8\x1f\xf0\x4d\x7c\x0b\x4a\x36\xd0\x22\xe6\x60\xbd\x79\x7a\xef\xd9\xe3\xf9\x75\xa7\xff\x1d\x00\x6e\x01\xb8\x07\xe0\x29\x80\xdb\x00\x66\xe8\xea\x23\x80\x07\x00\x34\x80\xbb\x00\xbe\x01\xf8\x79\x00\xfc\x00\x70\x08\xe0\x4d\xaf\xf3\xb6\x3d\xe0\x60\xef\xe9\xed\xf3\x76\x15\x39\xc4\x0f\x6d\xbd\xf1\xba\xee\xdf\xc0\xf8\x0f\x87\xe8\x8d\xad\xfa\x37\x30\x16\xde\x7d\xe2\x55\xa4\xd3\x92\xde\xb3\x0f\xc6\x59\x25\x2a\x8e\x91\xaf\x22\x55\x8e\xf8\x4a\x37\x6d\xcd\x81\xd6\x5c\xd7\x2e\x39\xe7\xd6\xf9\x48\xf3\x50\x99\x92\x26\x9b\x2a\x50\xe1\x94\x48\x16\x67\x05\x4d\x3d\xeb\x68\x9c\xa5\x57\x3a\xb2\x12\xb9\xcc\x06\x94\xe5\x94\xe5\x22\x97\x4a\x0e\x1e\x4b\x29\x65\xb2\x38\xa3\x73\xfe\x6c\xc2\x3f\xba\xa3\x9d\x6e\x20\xf2\x4c\x0d\x9e\x91\x1c\x4a\x99\xcc\x74\x88\x54\x78\x6d\x43\xad\xa3\xf3\x4a\x4c\x3c\xdb\x52\x5b\x31\xd9\x78\x1b\xc4\xf3\x65\xd7\xa6\x65\xba\xdc\x12\x2f\xab\x46\x9b\x3a\x5d\xb9\xe6\x45\x32\x3f\x9d\x1f\x5f\x8f\x92\xa5\x32\x99\x3a\x1b\xd9\x46\x2a\xbe\xb6\xac\xc4\x76\xb2\x27\x6d\xad\x8d\x1d\x89\xd5\x5a\xfb\xc0\x71\xfc\xae\x38\xa1\xe1\xb5\x6e\x7b\xef\x25\x7b\x3a\xb6\x2b\x57\x1a\x5b\x29\x31\x5c\x9a\x98\x5c\xd0\x6b\xb6\xec\xbb\x07\x2d\x1c\x97\x26\x8a\x2c\x3d\x4a\x33\x99\x5c\x50\xd7\xd3\x5b\xb7\xf1\x2b\x9e\x76\xb9\x4a\x74\xc1\x33\x6d\xab\x8d\xae\x98\x0a\xd6\xcd\xf6\xbb\x76\x2b\xa1\x13\xe7\x9b\xa0\x84\xed\x36\x14\xc6\xf9\x48\x74\x70\xfc\xd0\x8a\xfb\x63\x91\x3d\x1a\xfd\xb5\x2a\xc1\x36\x41\x5c\xb3\x67\xf1\x45\x07\x71\x58\x0a\x13\xb9\xf9\xc3\x6c\x8f\x3d\x15\x70\xe9\x1c\x7e\x07\x00\x00\xff\xff\x59\x11\x2e\xef\x74\x02\x00\x00") +var _translationsTestDefaultLc_messagesK8sMo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x64\x91\xc1\x8e\xd3\x30\x10\x86\xb3\x4b\xb9\xe4\xc8\x85\x0b\x87\x41\x68\x25\x10\x9a\x92\xb4\xb0\xaa\x5c\x8a\x50\xcb\x2e\x5a\xd4\x8a\x6a\x09\x88\x1b\xb8\xc9\x6c\x1a\x94\xd8\x91\x3d\x81\xe5\x01\x78\x04\x8e\xbc\x01\xcf\xc4\xb3\x30\xa9\x0b\xbb\x88\x51\xbe\x78\x3c\xf9\xe7\x77\x6c\xff\xba\x35\xf8\x1e\x49\xdc\x10\xee\x08\x8f\x85\x9b\xc2\x32\x0a\xf1\x51\xb8\x27\x68\xe1\xb6\xf0\x4d\xf8\x79\x10\x45\x3f\x64\x3c\x12\x5e\x1d\x86\xde\x56\xc6\x83\x7d\xcf\xe1\xde\x6f\x17\x4c\x9e\x3f\xb4\x75\xe7\x74\x3d\xb8\x96\x47\xff\xe5\x9e\x5d\x65\xca\xc1\xb5\x3c\x5a\x3b\xfb\x89\x72\xc6\xb3\x02\xdf\x91\xf3\x95\x35\x0a\x4a\x62\xa6\x4b\xc6\xd2\x22\x5d\xea\xa6\xad\xc9\xe3\x96\xea\xda\xc6\xe7\xd4\x5a\xc7\xb8\xf2\x65\x55\xe0\xbc\x2b\x3d\x66\x56\x41\xbc\x7e\x9d\xe1\xc2\x91\x66\x69\xc7\x17\x9a\x49\xc1\x28\x49\xc7\x98\x8e\xe4\x91\x54\x25\xe3\x87\x89\x84\x08\xf1\x9c\x3e\x57\xfe\x1f\xdd\xf1\x4e\x37\x86\x51\xaa\xc6\x4f\x30\x99\x88\x6e\xa9\x3d\x63\xe6\xb4\xf1\xb5\x66\xeb\x14\xcc\x1d\x99\x42\x1b\x98\x77\xce\x78\x78\xba\x09\xd3\x61\x31\xdc\xf4\x85\xe7\x65\xa3\xab\x7a\x98\xdb\xe6\x59\xbc\x3a\x5b\x9d\x5c\x6d\x25\x1d\x26\xf1\xc2\x1a\x26\x23\x7e\x5f\x5b\x59\xb0\xdf\xd9\xa3\xb6\xd6\x95\x99\x42\xbe\xd5\xce\x13\xcf\xde\x66\xa7\x38\xb9\xd2\xf5\xeb\x5e\x90\xc3\x13\x93\xdb\x42\x0e\x49\xc1\x64\x53\x71\xfc\x1e\x5f\x92\x21\x17\x7e\x68\x6d\xa9\xa8\x58\xfc\x8f\x87\x69\x22\x9f\xc2\x1c\xdf\xd8\xce\xe5\xb4\x08\xbe\x0a\x82\xf1\x52\x9b\xb2\xd3\x25\x61\x46\xba\xe9\x8f\x6b\x77\x25\x78\x6a\x5d\xe3\x15\x98\x70\x43\x7e\x36\x9a\x42\x48\x67\xf7\x0d\xdc\x9d\x41\xfa\x60\xfa\xb7\x55\x01\x99\x38\xe2\x2d\x39\x82\x2f\xda\xc3\x51\x01\x15\x53\xf3\xa7\xd2\xbf\xf6\x25\x1f\x5d\x58\x1b\xfd\x0e\x00\x00\xff\xff\x59\x11\x2e\xef\x74\x02\x00\x00") func translationsTestDefaultLc_messagesK8sMoBytes() ([]byte, error) { return bindataRead( @@ -175,7 +175,7 @@ func translationsTestDefaultLc_messagesK8sMo() (*asset, error) { return a, nil } -var _translationsTestDefaultLc_messagesK8sPo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x74\x52\x61\x6f\xd3\x30\x10\xfd\x9e\x5f\x71\xa4\x42\xda\x04\x0e\x49\x2a\xa6\x29\xa3\x88\x2d\xb4\xa3\x62\xd5\xaa\x2e\x43\x48\x80\x90\x9b\x5c\x13\x43\x62\x47\xbe\x0b\x74\xff\x1e\x39\xc9\xa8\xca\xc4\x97\xc8\x7e\xef\xdd\x3d\xbf\xcb\x4d\x20\x43\x62\x60\x2b\x35\xd5\x92\x95\xd1\x04\x3b\x63\xa1\xd3\x8a\x81\x91\x98\x02\x6f\x02\xa9\x69\x1f\xac\x2a\x2b\x86\x93\xf4\x14\xe2\x30\x3a\xf3\x26\x90\x55\x8a\x60\xa7\x6a\x04\x45\x50\x28\x62\xab\xb6\x1d\x63\x01\x9d\x2e\xd0\x02\x57\x08\x24\x1b\x84\x5a\xe5\xa8\x09\x41\x52\x8f\xad\x2f\xd3\x8f\x97\xd7\x73\x68\x65\xfe\x53\x96\xe8\xda\x2f\x96\x9b\xbb\x0c\x2e\xef\xb3\x0f\xb7\x1b\xd8\x5a\xd4\x85\xd4\x41\x11\x6c\x3b\xab\xe9\x5d\xd9\x48\x55\x07\xb9\x69\x5e\xf6\xc6\x81\x37\xf1\x1a\x2a\x55\x01\xbe\xef\x0e\xc4\xd6\x9d\xfc\xb5\x35\x3f\x30\x67\xb1\x2c\xc4\x27\xb4\xa4\x8c\x4e\xa0\x44\x66\xdc\xb3\x28\x8d\xc0\xbd\x6c\xda\x1a\x49\x54\x58\xd7\xe6\xab\xf6\x3d\x7f\x83\xad\xb1\x2c\x56\xae\x99\xb8\xea\x4a\x12\x99\x49\xa0\xa7\xd6\xb7\x99\x48\x2d\xf6\xf3\x10\xef\x25\x63\xe2\xbc\xa7\x22\x8a\x45\x14\x43\x1c\x26\xe1\xf4\x45\x18\x86\xe1\x28\x16\x1b\xfc\xa5\xe8\x48\x7b\xd6\x6b\xa7\x10\x47\xc9\xf4\xb5\x08\xcf\x47\xed\x8d\x24\x16\xd9\x38\x6c\x63\x13\xb8\x1a\xd2\xc2\x95\xcb\x0a\x6f\xfe\x1b\xfe\x6d\x5f\xbe\x5a\xae\xe6\x87\x78\x51\x30\x34\x4d\x8d\x66\xd4\x2c\xb2\x87\x16\x13\x70\x89\x5f\xb5\xb5\x54\xfa\x02\xf2\x4a\x5a\x42\x9e\xdd\x67\x0b\x71\x7e\xac\x75\x6f\xd8\xa1\x15\x73\x9d\x9b\x42\xe9\x32\x81\xf3\xad\xe2\x5e\xf3\x59\x5c\xa3\x46\x3b\x3c\x70\x6d\xb0\x50\x0c\x51\x70\x16\x44\xe1\x48\x0f\x98\xb8\x33\x9d\xcd\x31\x1d\x3c\x12\x38\x98\xdc\x48\x5d\x76\xb2\x44\x91\xa1\x6c\x1e\x47\x5a\x77\x56\xd6\x62\x61\x6c\x43\x09\xe8\xb6\xbf\xd2\x2c\xbe\x80\xe1\x38\x3b\xd1\xf0\x6c\x06\xd1\xe9\xc5\x51\x8b\x04\x50\x3b\xc0\xfd\xea\x9c\xf7\x0c\xbe\x5b\xca\xef\x6e\xd9\x74\xe9\x3f\x6e\xc2\xbf\x58\xbf\x14\x3b\x63\x9e\xd4\x0d\x5e\xc7\x75\x47\xd8\x78\x7b\x4a\x11\xdb\x2f\xe1\x37\xf0\xb9\x42\x8b\xf0\x5b\x12\x3c\x2f\x40\x31\x36\x7f\xd9\xe8\xc0\xba\xcf\x48\x93\xef\xfd\x09\x00\x00\xff\xff\xbf\xc0\xcb\xd2\x64\x03\x00\x00") +var _translationsTestDefaultLc_messagesK8sPo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x74\x52\x61\x6f\xd3\x30\x10\xfd\xde\x5f\x71\x64\x42\xda\x04\x0e\x49\x2b\xaa\x2a\xa5\x88\x36\xb4\xa3\x62\xd5\xaa\x2e\x43\x48\x80\x90\x9b\x5c\x13\x43\x62\x47\xb6\x03\xdd\xbf\xe7\x9c\x64\x54\x65\x22\x8a\x92\xf3\x7b\xef\xee\xf9\xec\xbb\x80\x04\x8d\x05\xab\xb9\x34\x25\xb7\x42\x49\x03\x07\xa5\xa1\x91\x82\x50\xa2\x8c\x3f\xb8\x80\x58\xd5\x0f\x5a\xe4\x85\x85\xcb\xf8\x0a\x86\x41\x38\x26\x30\x29\x04\x69\x45\x89\x40\xff\x4c\x18\xab\xc5\xbe\xb1\x98\x51\x6e\x86\x1a\x6c\x81\x60\x78\x85\x50\x8a\x14\xa5\x41\xe0\xa6\xc5\xb6\xf3\xf8\xe3\xfc\x7a\x09\x35\x4f\x7f\xf2\x1c\x5d\xf9\xd5\x7a\x77\x97\xc0\xfc\x3e\xf9\x70\xbb\x83\xbd\x46\x99\x71\xe9\x67\xfe\xbe\xd1\xd2\xbc\xcb\x2b\x2e\x4a\x3f\x55\xd5\xcb\xd6\x98\xf4\x83\xca\xe4\x22\x03\xcf\x73\x01\xd9\xba\xc8\xdb\x6a\xf5\x03\x53\xcb\xd6\x19\xfb\x84\xda\x50\x23\x11\xe4\x68\x2d\x1e\x2d\xcb\x15\xc3\x23\xaf\xea\x12\x0d\x2b\xb0\x2c\xd5\x57\x49\x19\x3b\xac\x95\xb6\x6c\xe3\x8a\xb1\x45\x93\x1b\x96\xa8\x08\x5a\x6a\x7b\x9b\xb0\x58\x63\x7b\x1e\xec\x3d\xb7\x18\x39\xef\x11\x0b\x87\xf4\x52\x18\x05\xa3\x17\x01\x3d\xbd\x98\xed\xf0\x97\x30\x67\xda\x71\xab\x1d\xc1\x30\x8c\x46\xaf\x59\x30\xe9\xb5\x37\xdc\x58\x96\xf4\x87\xad\x74\x04\x8b\xae\x5b\x58\xb8\x5e\xe1\xcd\x7f\x9b\x7f\xdb\xa6\x6f\xd6\x9b\xe5\xa9\xbd\xd0\xef\x8a\xc6\x4a\x5a\x94\x54\xf7\xa1\x26\x73\xd7\xf1\xab\xba\xe4\x42\x4e\x21\x2d\xb8\x36\x68\x67\xf7\xc9\x8a\x4d\xce\xb5\x6e\x0f\x07\xd4\x6c\x29\x53\x95\x09\x99\x47\x30\xd9\x0b\xdb\x6a\x3e\xb3\x6b\x94\xa8\xbb\x0d\x6e\x15\x66\x34\x0a\xa1\x3f\xf6\xc3\xa0\xa7\x3b\x8c\xdd\xa9\x46\xa7\x18\x77\x1e\x11\x9c\x4c\x6e\xb8\xcc\x1b\xba\x5b\x96\x20\xaf\x1e\x8f\xb4\x6c\x34\x2f\xd9\x4a\xe9\xca\x44\x20\xeb\x76\x69\x66\xc3\x29\x74\xe1\xec\x52\xc2\xb3\x19\x84\x57\xd3\xb3\x12\x11\xa0\x74\x80\xbb\xea\xd4\x1e\x2d\x78\x6e\x28\xbf\xbb\x61\x93\xb9\xf7\x38\x09\xff\x62\xed\x50\x1c\x94\x7a\x92\xd7\x79\x9d\xe7\x9d\x61\xfd\xea\x29\x45\x25\xbf\x04\xdf\x08\x2f\x50\x23\xfc\xa6\x61\x7e\x9e\x81\xb0\x58\xfd\x65\xc3\x13\xeb\x3e\x3d\x6d\xbc\xc1\x9f\x00\x00\x00\xff\xff\xbf\xc0\xcb\xd2\x64\x03\x00\x00") func translationsTestDefaultLc_messagesK8sPoBytes() ([]byte, error) { return bindataRead( @@ -195,7 +195,7 @@ func translationsTestDefaultLc_messagesK8sPo() (*asset, error) { return a, nil } -var _translationsTestEn_usLc_messagesK8sMo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x64\x51\xc1\x6e\x13\x31\x10\x7d\x0d\xe1\xb2\x47\x2e\x5c\x38\x18\xa1\x4a\x20\x34\x8b\x77\x83\xaa\xc8\x21\x08\x25\xb4\xa8\x28\x51\xa3\xb2\xa0\xde\xc0\xc9\x0e\x1b\xa3\x5d\x7b\x65\x3b\x50\xb8\xf3\x09\x1c\xf9\x03\xbe\x89\x6f\x41\xc9\x06\x5a\xd4\x39\x58\x6f\x9e\xde\x7b\xf6\x78\x7e\xdf\xe9\xff\x00\x80\x5b\x00\xee\x01\x78\x0a\xe0\x36\x80\x19\xba\xfa\x00\xe0\x01\x00\x0d\xe0\x2e\x80\xef\x00\x7e\x1d\x00\x3f\x01\x1c\x02\x78\xdd\xeb\xbc\x6d\x0f\x38\xd8\x7b\x7a\xfb\xbc\x5d\x45\x0e\xf1\x7d\x5b\x6f\xbc\xae\xfb\xd7\x30\x6e\xe0\x10\xbd\xb1\x55\xff\x1a\xc6\xc2\xbb\x4f\xbc\x8a\x74\x5a\xd2\x3b\xf6\xc1\x38\xab\x44\xc5\x31\xf2\x65\xa4\xca\x11\x5f\xea\xa6\xad\x39\xd0\x9a\xeb\xda\x25\xe7\xdc\x3a\x1f\x69\x1e\x2a\x53\xd2\x64\x53\x05\x2a\x9c\x12\xc9\xe2\xac\xa0\xa9\x67\x1d\x8d\xb3\xf4\x52\x47\x56\x22\x97\xd9\x80\xb2\x9c\xb2\x5c\xe4\x52\xc9\xc1\x63\x29\xa5\x4c\x16\x67\x74\xce\x9f\x4d\xf8\x4f\x77\xb4\xd3\x0d\x44\x9e\xab\x2c\x27\x39\x94\x32\x99\xe9\x10\xa9\xf0\xda\x86\x5a\x47\xe7\x95\x98\x78\xb6\xa5\xb6\x62\xb2\xf1\x36\x88\x67\xcb\xae\x4d\xcb\x74\xb9\x25\x5e\x54\x8d\x36\x75\xba\x72\xcd\xf3\x64\x7e\x3a\x3f\xbe\x1a\x25\x4b\x65\x32\x75\x36\xb2\x8d\x54\x7c\x6d\x59\x89\xed\x64\x4f\xda\x5a\x1b\x3b\x12\xab\xb5\xf6\x81\xe3\xf8\x6d\x71\x42\xc3\x2b\xdd\xf6\xde\x8f\xec\xe9\xd8\xae\x5c\x69\x6c\xa5\xc4\x70\x69\x62\x72\x41\xaf\xd8\xb2\xef\x1e\xb4\x70\x5c\x9a\x28\xb2\xf4\x28\xcd\x64\x72\x41\x5d\x4f\x6f\xdc\xc6\xaf\x78\xda\xe5\x2a\xd1\x05\xcf\xb4\xad\x36\xba\x62\x2a\x58\x37\xdb\xef\xda\xad\x84\x4e\x9c\x6f\x82\x12\xb6\xdb\x50\x18\xe7\x23\xd1\xc1\xf1\x43\x2b\xee\x8f\x45\xf6\x68\xf4\xcf\xaa\x04\xdb\x04\x71\xcd\x9e\xc5\x17\x1d\xc4\x61\x29\x4c\xe4\xe6\x2f\xb3\x3d\xf6\x54\xc0\x52\x7f\xc3\x9f\x00\x00\x00\xff\xff\xa9\x73\xeb\x8c\x74\x02\x00\x00") +var _translationsTestEn_usLc_messagesK8sMo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x64\x91\xc1\x6e\xd3\x40\x10\x86\xdd\x12\x2e\x3e\x72\xe1\xc2\x61\x10\xaa\x04\x42\x63\x6c\x07\x55\xd1\x86\x20\x94\xd0\xa2\xa2\x44\x44\xc5\x20\x6e\xb0\xb1\x07\xc7\xc8\xde\xb5\x76\xc7\x50\xb8\xf3\x08\x1c\x79\x03\x9e\x89\x67\x61\x1c\x07\x5a\xd4\x91\x3f\xef\xbf\xe3\x99\x7f\xbd\xbb\xbf\x6f\x8d\x7e\x04\x12\x37\x84\x3b\xc2\x63\xe1\xa6\xb0\x0c\x86\xf8\x20\xdc\x13\xb4\x70\x5b\xf8\x2e\xfc\x3a\x08\x82\x9f\x32\x1e\x09\x2f\x0f\x87\xde\x56\xc6\x83\x7d\xcf\xe1\xde\x6f\x17\x4c\x9e\xdf\xb7\x75\xe7\x74\x3d\xba\xa2\x83\x6b\xda\xb3\xab\x4c\x39\xba\xa2\x83\xb5\xb3\x9f\x28\x67\x3c\x2b\xf0\x2d\x39\x5f\x59\xa3\xa0\x24\x66\xba\x60\x2c\x2d\xd2\x85\x6e\xda\x9a\x3c\x6e\xa9\xae\x6d\x78\x4e\xad\x75\x8c\x2b\x5f\x56\x05\xce\xbb\xd2\x63\x66\x15\x84\xeb\x57\x19\x2e\x1c\x69\x96\x76\x7c\xae\x99\x14\xa4\x71\x32\xc6\x24\x95\x47\xa4\x8a\xc7\x0f\x63\x09\x29\xc4\x73\xfa\x5c\xf9\xff\xea\x8e\x77\x75\x63\x48\x53\x25\x22\x9e\x48\xdd\x52\x7b\xc6\xcc\x69\xe3\x6b\xcd\xd6\x29\x98\x3b\x32\x85\x36\x30\xef\x9c\xf1\xf0\x64\x33\x4c\xa3\x22\xda\xf4\x89\x67\x65\xa3\xab\x3a\xca\x6d\xf3\x34\x5c\x9d\xad\x4e\x2e\xb7\x92\x44\x71\xb8\xb0\x86\xc9\x88\xdf\xd7\x56\x16\xec\x77\xf6\xa8\xad\x75\x65\xa6\x90\x6f\xb5\xf3\xc4\xb3\x37\xd9\x29\x4e\x2e\xeb\xfa\x75\x3f\x92\xc3\x13\x93\xdb\x42\x0e\x49\xc1\x64\x53\x71\xf8\x0e\x5f\x90\x21\x37\xfc\xd0\xda\x52\x51\xb1\xf8\x1f\x47\x49\x2c\x9f\x86\x39\xbe\xb6\x9d\xcb\x69\x31\xf8\x2a\x18\x8c\x97\xda\x94\x9d\x2e\x09\x33\xd2\x4d\x7f\x5c\xbb\x2b\xc1\x53\xeb\x1a\xaf\xc0\x0c\x37\xe4\x67\xe9\x14\x06\x39\xbb\x6f\xe0\xee\x0c\x92\x07\xd3\x7f\xad\x0a\xc8\x84\x01\x6f\xc9\x11\x7c\xd1\x1e\x8e\x0a\xa8\x98\x9a\xbf\x99\xfe\xb5\x4f\xf9\x60\xa3\xbf\x05\x7f\x02\x00\x00\xff\xff\xa9\x73\xeb\x8c\x74\x02\x00\x00") func translationsTestEn_usLc_messagesK8sMoBytes() ([]byte, error) { return bindataRead( @@ -215,7 +215,7 @@ func translationsTestEn_usLc_messagesK8sMo() (*asset, error) { return a, nil } -var _translationsTestEn_usLc_messagesK8sPo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x74\x52\x61\x6f\xd3\x30\x10\xfd\x9e\x5f\x71\xa4\x42\xda\x04\x0e\x49\x26\x4d\x53\x46\x11\x6b\x68\x47\xc5\xaa\x55\x5d\x86\x90\x00\x21\x37\xb9\x26\x86\xc4\x8e\x7c\x17\xe8\xf8\xf5\xc8\x49\x46\x55\x26\xbe\x44\xf6\x7b\xef\xee\xf9\x5d\x6e\x02\x19\x12\x03\x5b\xa9\xa9\x96\xac\x8c\x26\xd8\x19\x0b\x9d\x56\x0c\x8c\xc4\x14\x78\x13\x48\x4d\xfb\x60\x55\x59\x31\x9c\xa4\xa7\x10\x87\xd1\xb9\x37\x81\xac\x52\x04\x3b\x55\x23\x28\x82\x42\x11\x5b\xb5\xed\x18\x0b\xe8\x74\x81\x16\xb8\x42\x20\xd9\x20\xd4\x2a\x47\x4d\x08\x92\x7a\x6c\x7d\x95\x7e\xb8\xba\x9e\x43\x2b\xf3\x1f\xb2\x44\xd7\x7e\xb1\xdc\xdc\x65\x70\x75\x9f\xbd\xbf\xdd\xc0\xd6\xa2\x2e\xa4\x0e\x8a\x60\xdb\x59\x4d\x6f\xcb\x46\xaa\x3a\xc8\x4d\xf3\xb2\x37\x0e\xbc\x89\xd7\x50\xa9\x0a\xf0\x7d\x77\x20\xb6\xee\xe4\xaf\xad\xf9\x8e\x39\x8b\x65\x21\x3e\xa2\x25\x65\x74\x02\x25\x32\xe3\x9e\x45\x69\x04\xee\x65\xd3\xd6\x48\xa2\xc2\xba\x36\x5f\xb4\xef\xf9\x1b\x6c\x8d\x65\xb1\x72\xcd\xc4\xac\x2b\x49\x64\x26\x81\x9e\x5a\xdf\x66\x22\xb5\xd8\xcf\x43\xbc\x93\x8c\x89\xf3\x3e\x13\x51\x2c\xa2\x18\xe2\x30\x09\xcf\x5e\x84\x61\x18\x8e\x62\xb1\xc1\x9f\x8a\x8e\xb4\xe7\xbd\xf6\x0c\xe2\x38\x89\x62\x11\x5e\x8c\xda\x1b\x49\x2c\xb2\x71\xd8\xc6\x26\x30\x1b\xd2\xc2\xcc\x65\x85\xd7\xff\x0d\xff\xa6\x2f\x5f\x2d\x57\xf3\x43\xbc\x28\x18\x9a\xa6\x46\x33\x6a\x16\xd9\x43\x8b\x09\xb8\xc4\xaf\xda\x5a\x2a\x7d\x09\x79\x25\x2d\x21\x4f\xef\xb3\x85\xb8\x38\xd6\xba\x37\xec\xd0\x8a\xb9\xce\x4d\xa1\x74\x99\xc0\xc5\x56\x71\xaf\xf9\x24\xae\x51\xa3\x1d\x1e\xb8\x36\x58\x28\x86\x28\x38\x0f\xa2\x70\xa4\x07\x4c\xdc\x99\xce\xe6\x98\x0e\x1e\x09\x1c\x4c\x6e\xa4\x2e\x3b\x59\xa2\xc8\x50\x36\x8f\x23\xad\x3b\x2b\x6b\xb1\x30\xb6\xa1\x04\x74\xdb\x5f\x69\x1a\x5f\xc2\x70\x9c\x9e\x68\x78\x36\x85\xe8\xf4\xf2\xa8\x45\x02\xa8\x1d\xe0\x7e\x75\xce\x7b\x06\xdf\x2d\xe5\x37\xb7\x6c\xba\xf4\x1f\x37\xe1\x5f\xac\x5f\x8a\xad\xfc\xfd\xa4\x6e\xf0\x3a\xae\x3b\xc2\xc6\xdb\x53\x8a\xd8\x7e\x0e\xbf\x82\xcf\x15\x5a\x84\x5f\x92\xe0\x79\x01\x8a\xb1\xf9\xcb\x46\x07\xd6\x7d\x46\x9a\x7c\xef\x4f\x00\x00\x00\xff\xff\x03\xfe\xb1\xf0\x64\x03\x00\x00") +var _translationsTestEn_usLc_messagesK8sPo = []byte("\x1f\x8b\x08\x00\x00\x09\x6e\x88\x00\xff\x74\x52\x61\x6f\xd3\x30\x10\xfd\xbe\x5f\x71\x64\x42\xda\x04\x0e\x49\x2b\x55\x55\x4a\x11\x6d\x68\x47\xc5\xaa\x55\x5d\x86\x90\x00\x21\x37\xb9\x25\x86\xc4\x8e\x6c\x07\x3a\x7e\x3d\xe7\x24\xa3\x0a\x13\x51\x94\x9c\xdf\x7b\x77\xcf\x67\xdf\x39\x24\x68\x2c\x58\xcd\xa5\x29\xb9\x15\x4a\x1a\xb8\x57\x1a\x1a\x29\x08\x25\xca\xf8\x67\xe7\x10\xab\xfa\x41\x8b\xbc\xb0\x70\x11\x5f\xc2\x28\x08\x27\x04\x26\x85\x20\xad\x28\x11\xe8\x9f\x09\x63\xb5\x38\x34\x16\x33\xca\xcd\x50\x83\x2d\x10\x0c\xaf\x10\x4a\x91\xa2\x34\x08\xdc\xb4\xd8\x6e\x11\x7f\x58\x5c\xad\xa0\xe6\xe9\x0f\x9e\xa3\x2b\xbf\xde\xec\x6f\x13\x58\xdc\x25\xef\x6f\xf6\x70\xd0\x28\x33\x2e\xfd\xcc\x3f\x34\x5a\x9a\xb7\x79\xc5\x45\xe9\xa7\xaa\x7a\xd9\x1a\x93\xfe\xac\x32\xb9\xc8\xc0\xf3\x5c\x40\xb6\x2e\xf2\x76\x5a\x7d\xc7\xd4\xb2\x4d\xc6\x3e\xa2\x36\xd4\x48\x04\x39\x5a\x8b\x47\xcb\x72\xc5\xf0\xc8\xab\xba\x44\xc3\x0a\x2c\x4b\xf5\x45\x52\xc6\x1e\x6b\xa5\x2d\xdb\xba\x62\x6c\xd9\xe4\x86\x25\x2a\x82\x96\xda\xdd\x24\x2c\xd6\xd8\x9e\x07\x7b\xc7\x2d\x46\xce\x7b\xcc\xc2\x11\xbd\x14\x46\xc1\xf8\x45\x40\x4f\x2f\x66\x7b\xfc\x29\xcc\x40\x3b\x69\xb5\x63\x18\x8d\x22\x0a\x82\x69\xaf\xbd\xe6\xc6\xb2\xa4\x3f\x6c\xa5\x23\x58\x76\xdd\xc2\xd2\xf5\x0a\xaf\xff\xdb\xfc\x9b\x36\x7d\xbb\xd9\xae\x4e\xed\x85\x7e\x57\x34\x56\xd2\xa2\xa4\xba\x0f\x35\x99\xbb\x8e\x5f\xd5\x25\x17\x72\x06\x69\xc1\xb5\x41\x3b\xbf\x4b\xd6\x6c\x3a\xd4\xba\x3d\xdc\xa3\x66\x2b\x99\xaa\x4c\xc8\x3c\x82\xe9\x41\xd8\x56\xf3\x89\x5d\xa1\x44\xdd\x6d\x70\xa7\x30\xa3\x51\x08\xfd\x89\x1f\x06\x3d\xdd\x61\xec\x56\x35\x3a\xc5\xb8\xf3\x88\xe0\x64\x72\xcd\x65\xde\xd0\xdd\xb2\x04\x79\xf5\x78\xa4\x65\xa3\x79\xc9\xd6\x4a\x57\x26\x02\x59\xb7\x4b\x33\x1f\xcd\xa0\x0b\xe7\x17\x12\x9e\xcd\x21\xbc\x9c\x0d\x4a\x44\x80\xd2\x01\xee\xaa\x53\x7b\xb4\xe0\xb9\xa1\xfc\xe6\x86\x4d\xe6\xde\xe3\x24\xfc\x8b\xb5\x43\x71\xe0\xbf\x9f\xe4\x75\x5e\xc3\xbc\x01\xd6\xaf\x9e\x52\x54\xf2\x73\xf0\x95\xf0\x02\x35\xc2\x2f\x1a\xe6\xe7\x19\x08\x8b\xd5\x5f\x36\x3c\xb1\xee\xd3\xd3\xc6\x3b\xfb\x13\x00\x00\xff\xff\x03\xfe\xb1\xf0\x64\x03\x00\x00") func translationsTestEn_usLc_messagesK8sPoBytes() ([]byte, error) { return bindataRead( diff --git a/test/e2e/BUILD b/test/e2e/BUILD index be3ff447192..5391d7a18e4 100644 --- a/test/e2e/BUILD +++ b/test/e2e/BUILD @@ -151,7 +151,6 @@ go_library( "//pkg/controller/petset:go_default_library", "//pkg/controller/replicaset:go_default_library", "//pkg/controller/replication:go_default_library", - "//pkg/dns/federation:go_default_library", "//pkg/fields:go_default_library", "//pkg/kubectl:go_default_library", "//pkg/kubectl/cmd/util:go_default_library", diff --git a/test/e2e/dns_configmap.go b/test/e2e/dns_configmap.go index c9400f9309c..021f0c0d720 100644 --- a/test/e2e/dns_configmap.go +++ b/test/e2e/dns_configmap.go @@ -24,7 +24,6 @@ import ( "k8s.io/kubernetes/pkg/api/v1" metav1 "k8s.io/kubernetes/pkg/apis/meta/v1" clientset "k8s.io/kubernetes/pkg/client/clientset_generated/clientset" - fed "k8s.io/kubernetes/pkg/dns/federation" "k8s.io/kubernetes/pkg/fields" "k8s.io/kubernetes/pkg/labels" "k8s.io/kubernetes/pkg/util/intstr" @@ -43,6 +42,7 @@ type dnsConfigMapTest struct { labels []string cm *v1.ConfigMap + fedMap map[string]string isValid bool dnsPod *v1.Pod @@ -90,23 +90,25 @@ func (t *dnsConfigMapTest) run() { t.labels = []string{"abc", "ghi"} valid1 := map[string]string{"federations": t.labels[0] + "=def"} + valid1m := map[string]string{t.labels[0]: "def"} valid2 := map[string]string{"federations": t.labels[1] + "=xyz"} + valid2m := map[string]string{t.labels[1]: "xyz"} invalid := map[string]string{"federations": "invalid.map=xyz"} By("empty -> valid1") - t.setConfigMap(&v1.ConfigMap{Data: valid1}, true) + t.setConfigMap(&v1.ConfigMap{Data: valid1}, valid1m, true) t.validate() By("valid1 -> valid2") - t.setConfigMap(&v1.ConfigMap{Data: valid2}, true) + t.setConfigMap(&v1.ConfigMap{Data: valid2}, valid2m, true) t.validate() By("valid2 -> invalid") - t.setConfigMap(&v1.ConfigMap{Data: invalid}, false) + t.setConfigMap(&v1.ConfigMap{Data: invalid}, nil, false) t.validate() By("invalid -> valid1") - t.setConfigMap(&v1.ConfigMap{Data: valid1}, true) + t.setConfigMap(&v1.ConfigMap{Data: valid1}, valid1m, true) t.validate() By("valid1 -> deleted") @@ -114,7 +116,7 @@ func (t *dnsConfigMapTest) run() { t.validate() By("deleted -> invalid") - t.setConfigMap(&v1.ConfigMap{Data: invalid}, false) + t.setConfigMap(&v1.ConfigMap{Data: invalid}, nil, false) t.validate() } @@ -123,11 +125,7 @@ func (t *dnsConfigMapTest) validate() { } func (t *dnsConfigMapTest) validateFederation() { - federations := make(map[string]string) - if t.cm != nil { - err := fed.ParseFederationsFlag(t.cm.Data["federations"], federations) - Expect(err).NotTo(HaveOccurred()) - } + federations := t.fedMap if len(federations) == 0 { By(fmt.Sprintf("Validating federation labels %v do not exist", t.labels)) @@ -210,9 +208,10 @@ func (t *dnsConfigMapTest) runDig(dnsName string) []string { } } -func (t *dnsConfigMapTest) setConfigMap(cm *v1.ConfigMap, isValid bool) { +func (t *dnsConfigMapTest) setConfigMap(cm *v1.ConfigMap, fedMap map[string]string, isValid bool) { if isValid { t.cm = cm + t.fedMap = fedMap } t.isValid = isValid