From 1a60276b6e8818da080cb4ea9ed3fbf93ced6a1b Mon Sep 17 00:00:00 2001 From: Zihong Zheng Date: Fri, 9 Feb 2018 14:11:09 -0800 Subject: [PATCH 1/4] Promote configurable pod resolv.conf (CustomPodDNS) to Beta --- pkg/features/kube_features.go | 4 ++-- staging/src/k8s.io/api/core/v1/types.go | 2 -- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/features/kube_features.go b/pkg/features/kube_features.go index e312a250a55..5561d6be8f0 100644 --- a/pkg/features/kube_features.go +++ b/pkg/features/kube_features.go @@ -191,7 +191,7 @@ const ( CSIPersistentVolume utilfeature.Feature = "CSIPersistentVolume" // owner @MrHohn - // alpha: v1.9 + // beta: v1.10 // // Support configurable pod DNS parameters. CustomPodDNS utilfeature.Feature = "CustomPodDNS" @@ -272,7 +272,7 @@ var defaultKubernetesFeatureGates = map[utilfeature.Feature]utilfeature.FeatureS MountContainers: {Default: false, PreRelease: utilfeature.Alpha}, VolumeScheduling: {Default: false, PreRelease: utilfeature.Alpha}, CSIPersistentVolume: {Default: true, PreRelease: utilfeature.Beta}, - CustomPodDNS: {Default: false, PreRelease: utilfeature.Alpha}, + CustomPodDNS: {Default: true, PreRelease: utilfeature.Beta}, BlockVolume: {Default: false, PreRelease: utilfeature.Alpha}, StorageProtection: {Default: false, PreRelease: utilfeature.Alpha}, ResourceLimitsPriorityFunction: {Default: false, PreRelease: utilfeature.Alpha}, diff --git a/staging/src/k8s.io/api/core/v1/types.go b/staging/src/k8s.io/api/core/v1/types.go index d1b464fd406..141ad14aa6c 100644 --- a/staging/src/k8s.io/api/core/v1/types.go +++ b/staging/src/k8s.io/api/core/v1/types.go @@ -2808,7 +2808,6 @@ type PodSpec struct { // DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. // To have DNS options set along with hostNetwork, you have to specify DNS policy // explicitly to 'ClusterFirstWithHostNet'. - // Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it. // +optional DNSPolicy DNSPolicy `json:"dnsPolicy,omitempty" protobuf:"bytes,6,opt,name=dnsPolicy,casttype=DNSPolicy"` // NodeSelector is a selector which must be true for the pod to fit on a node. @@ -2905,7 +2904,6 @@ type PodSpec struct { // Specifies the DNS parameters of a pod. // Parameters specified here will be merged to the generated DNS // configuration based on DNSPolicy. - // This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it. // +optional DNSConfig *PodDNSConfig `json:"dnsConfig,omitempty" protobuf:"bytes,26,opt,name=dnsConfig"` } From 44a64edc5464242d23a66d7bdde798e702e50929 Mon Sep 17 00:00:00 2001 From: Zihong Zheng Date: Mon, 12 Feb 2018 13:51:37 -0800 Subject: [PATCH 2/4] Auto-generated files for CustomPodDNS Beta API --- api/openapi-spec/swagger.json | 4 ++-- api/swagger-spec/apps_v1.json | 4 ++-- api/swagger-spec/apps_v1beta1.json | 4 ++-- api/swagger-spec/apps_v1beta2.json | 4 ++-- api/swagger-spec/batch_v1.json | 4 ++-- api/swagger-spec/batch_v1beta1.json | 4 ++-- api/swagger-spec/batch_v2alpha1.json | 4 ++-- api/swagger-spec/extensions_v1beta1.json | 4 ++-- api/swagger-spec/v1.json | 4 ++-- docs/api-reference/apps/v1/definitions.html | 4 ++-- docs/api-reference/apps/v1beta1/definitions.html | 4 ++-- docs/api-reference/apps/v1beta2/definitions.html | 4 ++-- docs/api-reference/batch/v1/definitions.html | 4 ++-- docs/api-reference/batch/v1beta1/definitions.html | 4 ++-- docs/api-reference/batch/v2alpha1/definitions.html | 4 ++-- docs/api-reference/extensions/v1beta1/definitions.html | 4 ++-- docs/api-reference/v1/definitions.html | 4 ++-- staging/src/k8s.io/api/core/v1/generated.proto | 2 -- staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go | 4 ++-- 19 files changed, 36 insertions(+), 38 deletions(-) diff --git a/api/openapi-spec/swagger.json b/api/openapi-spec/swagger.json index 6e286b0737e..eccc7e15344 100644 --- a/api/openapi-spec/swagger.json +++ b/api/openapi-spec/swagger.json @@ -78935,11 +78935,11 @@ "x-kubernetes-patch-strategy": "merge" }, "dnsConfig": { - "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.", + "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.", "$ref": "#/definitions/io.k8s.api.core.v1.PodDNSConfig" }, "dnsPolicy": { - "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.", + "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'.", "type": "string" }, "hostAliases": { diff --git a/api/swagger-spec/apps_v1.json b/api/swagger-spec/apps_v1.json index bf7ebc59035..886835d863e 100644 --- a/api/swagger-spec/apps_v1.json +++ b/api/swagger-spec/apps_v1.json @@ -6652,7 +6652,7 @@ }, "dnsPolicy": { "type": "string", - "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'." }, "nodeSelector": { "type": "object", @@ -6738,7 +6738,7 @@ }, "dnsConfig": { "$ref": "v1.PodDNSConfig", - "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." } } }, diff --git a/api/swagger-spec/apps_v1beta1.json b/api/swagger-spec/apps_v1beta1.json index e4ca975a596..1bbf22bca44 100644 --- a/api/swagger-spec/apps_v1beta1.json +++ b/api/swagger-spec/apps_v1beta1.json @@ -4286,7 +4286,7 @@ }, "dnsPolicy": { "type": "string", - "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'." }, "nodeSelector": { "type": "object", @@ -4372,7 +4372,7 @@ }, "dnsConfig": { "$ref": "v1.PodDNSConfig", - "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." } } }, diff --git a/api/swagger-spec/apps_v1beta2.json b/api/swagger-spec/apps_v1beta2.json index aeb08804723..308b4027835 100644 --- a/api/swagger-spec/apps_v1beta2.json +++ b/api/swagger-spec/apps_v1beta2.json @@ -6652,7 +6652,7 @@ }, "dnsPolicy": { "type": "string", - "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'." }, "nodeSelector": { "type": "object", @@ -6738,7 +6738,7 @@ }, "dnsConfig": { "$ref": "v1.PodDNSConfig", - "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." } } }, diff --git a/api/swagger-spec/batch_v1.json b/api/swagger-spec/batch_v1.json index 5a0a7b1a76b..6eb485f7baf 100644 --- a/api/swagger-spec/batch_v1.json +++ b/api/swagger-spec/batch_v1.json @@ -1626,7 +1626,7 @@ }, "dnsPolicy": { "type": "string", - "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'." }, "nodeSelector": { "type": "object", @@ -1712,7 +1712,7 @@ }, "dnsConfig": { "$ref": "v1.PodDNSConfig", - "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." } } }, diff --git a/api/swagger-spec/batch_v1beta1.json b/api/swagger-spec/batch_v1beta1.json index 5dadb0bcd51..27eb44000ca 100644 --- a/api/swagger-spec/batch_v1beta1.json +++ b/api/swagger-spec/batch_v1beta1.json @@ -1681,7 +1681,7 @@ }, "dnsPolicy": { "type": "string", - "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'." }, "nodeSelector": { "type": "object", @@ -1767,7 +1767,7 @@ }, "dnsConfig": { "$ref": "v1.PodDNSConfig", - "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." } } }, diff --git a/api/swagger-spec/batch_v2alpha1.json b/api/swagger-spec/batch_v2alpha1.json index 454dc9133e8..73886e0b301 100644 --- a/api/swagger-spec/batch_v2alpha1.json +++ b/api/swagger-spec/batch_v2alpha1.json @@ -1681,7 +1681,7 @@ }, "dnsPolicy": { "type": "string", - "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'." }, "nodeSelector": { "type": "object", @@ -1767,7 +1767,7 @@ }, "dnsConfig": { "$ref": "v1.PodDNSConfig", - "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." } } }, diff --git a/api/swagger-spec/extensions_v1beta1.json b/api/swagger-spec/extensions_v1beta1.json index f45b77dec60..a525b54ba0f 100644 --- a/api/swagger-spec/extensions_v1beta1.json +++ b/api/swagger-spec/extensions_v1beta1.json @@ -7294,7 +7294,7 @@ }, "dnsPolicy": { "type": "string", - "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'." }, "nodeSelector": { "type": "object", @@ -7380,7 +7380,7 @@ }, "dnsConfig": { "$ref": "v1.PodDNSConfig", - "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." } } }, diff --git a/api/swagger-spec/v1.json b/api/swagger-spec/v1.json index 441cf975023..5bb3c5b95fb 100644 --- a/api/swagger-spec/v1.json +++ b/api/swagger-spec/v1.json @@ -21447,7 +21447,7 @@ }, "dnsPolicy": { "type": "string", - "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'." }, "nodeSelector": { "type": "object", @@ -21533,7 +21533,7 @@ }, "dnsConfig": { "$ref": "v1.PodDNSConfig", - "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it." + "description": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy." } } }, diff --git a/docs/api-reference/apps/v1/definitions.html b/docs/api-reference/apps/v1/definitions.html index 24e2dcf29e0..14ac8f65413 100755 --- a/docs/api-reference/apps/v1/definitions.html +++ b/docs/api-reference/apps/v1/definitions.html @@ -3804,7 +3804,7 @@ When an object is created, the system will populate this list with the current s

dnsPolicy

-

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet. Note that None policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet.

false

string

@@ -3937,7 +3937,7 @@ When an object is created, the system will populate this list with the current s

dnsConfig

-

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.

false

v1.PodDNSConfig

diff --git a/docs/api-reference/apps/v1beta1/definitions.html b/docs/api-reference/apps/v1beta1/definitions.html index 3af498120ab..2770acacbce 100755 --- a/docs/api-reference/apps/v1beta1/definitions.html +++ b/docs/api-reference/apps/v1beta1/definitions.html @@ -3857,7 +3857,7 @@ The StatefulSet guarantees that a given network identity will always map to the

dnsPolicy

-

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet. Note that None policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet.

false

string

@@ -3990,7 +3990,7 @@ The StatefulSet guarantees that a given network identity will always map to the

dnsConfig

-

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.

false

v1.PodDNSConfig

diff --git a/docs/api-reference/apps/v1beta2/definitions.html b/docs/api-reference/apps/v1beta2/definitions.html index 7cfa2d4fdd8..eaa4c255e5f 100755 --- a/docs/api-reference/apps/v1beta2/definitions.html +++ b/docs/api-reference/apps/v1beta2/definitions.html @@ -4473,7 +4473,7 @@ The StatefulSet guarantees that a given network identity will always map to the

dnsPolicy

-

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet. Note that None policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet.

false

string

@@ -4606,7 +4606,7 @@ The StatefulSet guarantees that a given network identity will always map to the

dnsConfig

-

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.

false

v1.PodDNSConfig

diff --git a/docs/api-reference/batch/v1/definitions.html b/docs/api-reference/batch/v1/definitions.html index b0113a35ecc..29ec6c77834 100755 --- a/docs/api-reference/batch/v1/definitions.html +++ b/docs/api-reference/batch/v1/definitions.html @@ -3137,7 +3137,7 @@ When an object is created, the system will populate this list with the current s

dnsPolicy

-

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet. Note that None policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet.

false

string

@@ -3270,7 +3270,7 @@ When an object is created, the system will populate this list with the current s

dnsConfig

-

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.

false

v1.PodDNSConfig

diff --git a/docs/api-reference/batch/v1beta1/definitions.html b/docs/api-reference/batch/v1beta1/definitions.html index eb90fd3bf8a..709c9ac7e5e 100755 --- a/docs/api-reference/batch/v1beta1/definitions.html +++ b/docs/api-reference/batch/v1beta1/definitions.html @@ -3171,7 +3171,7 @@ When an object is created, the system will populate this list with the current s

dnsPolicy

-

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet. Note that None policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet.

false

string

@@ -3304,7 +3304,7 @@ When an object is created, the system will populate this list with the current s

dnsConfig

-

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.

false

v1.PodDNSConfig

diff --git a/docs/api-reference/batch/v2alpha1/definitions.html b/docs/api-reference/batch/v2alpha1/definitions.html index 2cc20843342..9d1f65adfdc 100755 --- a/docs/api-reference/batch/v2alpha1/definitions.html +++ b/docs/api-reference/batch/v2alpha1/definitions.html @@ -3144,7 +3144,7 @@ When an object is created, the system will populate this list with the current s

dnsPolicy

-

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet. Note that None policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet.

false

string

@@ -3277,7 +3277,7 @@ When an object is created, the system will populate this list with the current s

dnsConfig

-

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.

false

v1.PodDNSConfig

diff --git a/docs/api-reference/extensions/v1beta1/definitions.html b/docs/api-reference/extensions/v1beta1/definitions.html index 6ac8e7e35de..703aeccd2a6 100755 --- a/docs/api-reference/extensions/v1beta1/definitions.html +++ b/docs/api-reference/extensions/v1beta1/definitions.html @@ -4496,7 +4496,7 @@ When an object is created, the system will populate this list with the current s

dnsPolicy

-

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet. Note that None policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet.

false

string

@@ -4629,7 +4629,7 @@ When an object is created, the system will populate this list with the current s

dnsConfig

-

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.

false

v1.PodDNSConfig

diff --git a/docs/api-reference/v1/definitions.html b/docs/api-reference/v1/definitions.html index ff90e1d21ff..932f603950e 100755 --- a/docs/api-reference/v1/definitions.html +++ b/docs/api-reference/v1/definitions.html @@ -9165,7 +9165,7 @@ Examples:

dnsPolicy

-

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet. Note that None policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are ClusterFirstWithHostNet, ClusterFirst, Default or None. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to ClusterFirstWithHostNet.

false

string

@@ -9298,7 +9298,7 @@ Examples:

dnsConfig

-

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.

+

Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.

false

v1.PodDNSConfig

diff --git a/staging/src/k8s.io/api/core/v1/generated.proto b/staging/src/k8s.io/api/core/v1/generated.proto index e5d8f74db65..f729cf9146e 100644 --- a/staging/src/k8s.io/api/core/v1/generated.proto +++ b/staging/src/k8s.io/api/core/v1/generated.proto @@ -3028,7 +3028,6 @@ message PodSpec { // DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. // To have DNS options set along with hostNetwork, you have to specify DNS policy // explicitly to 'ClusterFirstWithHostNet'. - // Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it. // +optional optional string dnsPolicy = 6; @@ -3142,7 +3141,6 @@ message PodSpec { // Specifies the DNS parameters of a pod. // Parameters specified here will be merged to the generated DNS // configuration based on DNSPolicy. - // This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it. // +optional optional PodDNSConfig dnsConfig = 26; } diff --git a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go index 2c274b13d91..0e1e8249f56 100644 --- a/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go +++ b/staging/src/k8s.io/api/core/v1/types_swagger_doc_generated.go @@ -1496,7 +1496,7 @@ var map_PodSpec = map[string]string{ "restartPolicy": "Restart policy for all containers within the pod. One of Always, OnFailure, Never. Default to Always. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy", "terminationGracePeriodSeconds": "Optional duration in seconds the pod needs to terminate gracefully. May be decreased in delete request. Value must be non-negative integer. The value zero indicates delete immediately. If this value is nil, the default grace period will be used instead. The grace period is the duration in seconds after the processes running in the pod are sent a termination signal and the time when the processes are forcibly halted with a kill signal. Set this value longer than the expected cleanup time for your process. Defaults to 30 seconds.", "activeDeadlineSeconds": "Optional duration in seconds the pod may be active on the node relative to StartTime before the system will actively try to mark it failed and kill associated containers. Value must be a positive integer.", - "dnsPolicy": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'. Note that 'None' policy is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.", + "dnsPolicy": "Set DNS policy for the pod. Defaults to \"ClusterFirst\". Valid values are 'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS parameters given in DNSConfig will be merged with the policy selected with DNSPolicy. To have DNS options set along with hostNetwork, you have to specify DNS policy explicitly to 'ClusterFirstWithHostNet'.", "nodeSelector": "NodeSelector is a selector which must be true for the pod to fit on a node. Selector which must match a node's labels for the pod to be scheduled on that node. More info: https://kubernetes.io/docs/concepts/configuration/assign-pod-node/", "serviceAccountName": "ServiceAccountName is the name of the ServiceAccount to use to run this pod. More info: https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/", "serviceAccount": "DeprecatedServiceAccount is a depreciated alias for ServiceAccountName. Deprecated: Use serviceAccountName instead.", @@ -1515,7 +1515,7 @@ var map_PodSpec = map[string]string{ "hostAliases": "HostAliases is an optional list of hosts and IPs that will be injected into the pod's hosts file if specified. This is only valid for non-hostNetwork pods.", "priorityClassName": "If specified, indicates the pod's priority. \"system-node-critical\" and \"system-cluster-critical\" are two special keywords which indicate the highest priorities with the former being the highest priority. Any other name must be defined by creating a PriorityClass object with that name. If not specified, the pod priority will be default or zero if there is no default.", "priority": "The priority value. Various system components use this field to find the priority of the pod. When Priority Admission Controller is enabled, it prevents users from setting this field. The admission controller populates this field from PriorityClassName. The higher the value, the higher the priority.", - "dnsConfig": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy. This is an alpha feature introduced in v1.9 and CustomPodDNS feature gate must be enabled to use it.", + "dnsConfig": "Specifies the DNS parameters of a pod. Parameters specified here will be merged to the generated DNS configuration based on DNSPolicy.", } func (PodSpec) SwaggerDoc() map[string]string { From 9e5e0c6a59cfbb20c3a7d07f6ce8c12fd1f32e6f Mon Sep 17 00:00:00 2001 From: Zihong Zheng Date: Wed, 21 Feb 2018 18:32:58 -0800 Subject: [PATCH 3/4] More unit test for configurable pod resolv.conf --- pkg/kubelet/network/dns/dns_test.go | 130 ++++++++++++++++++++++------ 1 file changed, 102 insertions(+), 28 deletions(-) diff --git a/pkg/kubelet/network/dns/dns_test.go b/pkg/kubelet/network/dns/dns_test.go index c784f081b7e..799e83510a7 100644 --- a/pkg/kubelet/network/dns/dns_test.go +++ b/pkg/kubelet/network/dns/dns_test.go @@ -18,7 +18,9 @@ package dns import ( "fmt" + "io/ioutil" "net" + "os" "strings" "testing" @@ -487,64 +489,134 @@ func TestGetPodDNSCustom(t *testing.T) { UID: types.UID("testNode"), Namespace: "", } - clusterNS := "203.0.113.1" + + testPodNamespace := "testNS" + testClusterNameserver := "10.0.0.10" testClusterDNSDomain := "kubernetes.io" - testClusterDNS := []net.IP{net.ParseIP(clusterNS)} - testOptionValue := "3" + testSvcDomain := fmt.Sprintf("svc.%s", testClusterDNSDomain) + testNsSvcDomain := fmt.Sprintf("%s.svc.%s", testPodNamespace, testClusterDNSDomain) + testNdotsOptionValue := "3" + testHostNameserver := "8.8.8.8" + testHostDomain := "host.domain" - configurer := NewConfigurer(recorder, nodeRef, nil, testClusterDNS, testClusterDNSDomain, "") - - pod := &v1.Pod{ + testPod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ - UID: "", - Name: "test_pod", - Namespace: "testNS", - Annotations: map[string]string{}, + Name: "test_pod", + Namespace: testPodNamespace, }, - Spec: v1.PodSpec{ - DNSPolicy: v1.DNSClusterFirst, - }, - } - clusterFirstDNSConfig, err := configurer.GetPodDNS(pod) - if err != nil { - t.Fatalf("Preparing clusterFirstDNSConfig: GetPodDNS(%v), unexpected error: %v", pod, err) } - // Overwrite DNSPolicy for testing. - pod.Spec.DNSPolicy = v1.DNSNone + resolvConfContent := []byte(fmt.Sprintf("nameserver %s\nsearch %s\n", testHostNameserver, testHostDomain)) + tmpfile, err := ioutil.TempFile("", "tmpResolvConf") + if err != nil { + t.Fatal(err) + } + defer os.Remove(tmpfile.Name()) + if _, err := tmpfile.Write(resolvConfContent); err != nil { + t.Fatal(err) + } + if err := tmpfile.Close(); err != nil { + t.Fatal(err) + } + + configurer := NewConfigurer(recorder, nodeRef, nil, []net.IP{net.ParseIP(testClusterNameserver)}, testClusterDNSDomain, tmpfile.Name()) testCases := []struct { desc string customPodDNSFeatureGate bool + hostnetwork bool + dnsPolicy v1.DNSPolicy dnsConfig *v1.PodDNSConfig expectedDNSConfig *runtimeapi.DNSConfig }{ { - desc: "feature gate is disabled, DNSNone should fallback to DNSClusterFirst", - expectedDNSConfig: clusterFirstDNSConfig, + desc: "feature gate is disabled, DNSNone should fallback to DNSClusterFirst", + dnsPolicy: v1.DNSNone, + expectedDNSConfig: &runtimeapi.DNSConfig{ + Servers: []string{testClusterNameserver}, + Searches: []string{testNsSvcDomain, testSvcDomain, testClusterDNSDomain, testHostDomain}, + Options: []string{"ndots:5"}, + }, }, { desc: "feature gate is enabled, DNSNone without DNSConfig should have empty DNS settings", customPodDNSFeatureGate: true, + dnsPolicy: v1.DNSNone, expectedDNSConfig: &runtimeapi.DNSConfig{}, }, { desc: "feature gate is enabled, DNSNone with DNSConfig should have a merged DNS settings", customPodDNSFeatureGate: true, + dnsPolicy: v1.DNSNone, dnsConfig: &v1.PodDNSConfig{ - Nameservers: []string{"10.0.0.10"}, + Nameservers: []string{"203.0.113.1"}, Searches: []string{"my.domain", "second.domain"}, Options: []v1.PodDNSConfigOption{ - {Name: "ndots", Value: &testOptionValue}, + {Name: "ndots", Value: &testNdotsOptionValue}, {Name: "debug"}, }, }, expectedDNSConfig: &runtimeapi.DNSConfig{ - Servers: []string{"10.0.0.10"}, + Servers: []string{"203.0.113.1"}, Searches: []string{"my.domain", "second.domain"}, Options: []string{"ndots:3", "debug"}, }, }, + { + desc: "feature gate is enabled, DNSClusterFirst with DNSConfig should have a merged DNS settings", + customPodDNSFeatureGate: true, + dnsPolicy: v1.DNSClusterFirst, + dnsConfig: &v1.PodDNSConfig{ + Nameservers: []string{"10.0.0.11"}, + Searches: []string{"my.domain"}, + Options: []v1.PodDNSConfigOption{ + {Name: "ndots", Value: &testNdotsOptionValue}, + {Name: "debug"}, + }, + }, + expectedDNSConfig: &runtimeapi.DNSConfig{ + Servers: []string{testClusterNameserver, "10.0.0.11"}, + Searches: []string{testNsSvcDomain, testSvcDomain, testClusterDNSDomain, testHostDomain, "my.domain"}, + Options: []string{"ndots:3", "debug"}, + }, + }, + { + desc: "feature gate is enabled, DNSClusterFirstWithHostNet with DNSConfig should have a merged DNS settings", + customPodDNSFeatureGate: true, + hostnetwork: true, + dnsPolicy: v1.DNSClusterFirstWithHostNet, + dnsConfig: &v1.PodDNSConfig{ + Nameservers: []string{"10.0.0.11"}, + Searches: []string{"my.domain"}, + Options: []v1.PodDNSConfigOption{ + {Name: "ndots", Value: &testNdotsOptionValue}, + {Name: "debug"}, + }, + }, + expectedDNSConfig: &runtimeapi.DNSConfig{ + Servers: []string{testClusterNameserver, "10.0.0.11"}, + Searches: []string{testNsSvcDomain, testSvcDomain, testClusterDNSDomain, testHostDomain, "my.domain"}, + Options: []string{"ndots:3", "debug"}, + }, + }, + { + desc: "feature gate is enabled, DNSDefault with DNSConfig should have a merged DNS settings", + customPodDNSFeatureGate: true, + dnsPolicy: v1.DNSDefault, + dnsConfig: &v1.PodDNSConfig{ + Nameservers: []string{"10.0.0.11"}, + Searches: []string{"my.domain"}, + Options: []v1.PodDNSConfigOption{ + {Name: "ndots", Value: &testNdotsOptionValue}, + {Name: "debug"}, + }, + }, + expectedDNSConfig: &runtimeapi.DNSConfig{ + Servers: []string{testHostNameserver, "10.0.0.11"}, + Searches: []string{testHostDomain, "my.domain"}, + Options: []string{"ndots:3", "debug"}, + }, + }, } for _, tc := range testCases { @@ -552,14 +624,16 @@ func TestGetPodDNSCustom(t *testing.T) { t.Errorf("Failed to set CustomPodDNS feature gate: %v", err) } - pod.Spec.DNSConfig = tc.dnsConfig + testPod.Spec.HostNetwork = tc.hostnetwork + testPod.Spec.DNSConfig = tc.dnsConfig + testPod.Spec.DNSPolicy = tc.dnsPolicy - resDNSConfig, err := configurer.GetPodDNS(pod) + resDNSConfig, err := configurer.GetPodDNS(testPod) if err != nil { - t.Errorf("%s: GetPodDNS(%v), unexpected error: %v", tc.desc, pod, err) + t.Errorf("%s: GetPodDNS(%v), unexpected error: %v", tc.desc, testPod, err) } if !dnsConfigsAreEqual(resDNSConfig, tc.expectedDNSConfig) { - t.Errorf("%s: GetPodDNS(%v)=%v, want %v", tc.desc, pod, resDNSConfig, tc.expectedDNSConfig) + t.Errorf("%s: GetPodDNS(%v)=%v, want %v", tc.desc, testPod, resDNSConfig, tc.expectedDNSConfig) } } } From a042ee345638d679db7afcdb1a230b56ea9c62d8 Mon Sep 17 00:00:00 2001 From: Zihong Zheng Date: Thu, 22 Feb 2018 23:20:47 -0800 Subject: [PATCH 4/4] Add e2e test for configurable pod resolv.conf --- test/e2e/network/dns.go | 351 ++++++++++----------------------- test/e2e/network/dns_common.go | 266 ++++++++++++++++++++++++- 2 files changed, 370 insertions(+), 247 deletions(-) diff --git a/test/e2e/network/dns.go b/test/e2e/network/dns.go index 556d4720820..7f41ced62f1 100644 --- a/test/e2e/network/dns.go +++ b/test/e2e/network/dns.go @@ -17,255 +17,22 @@ limitations under the License. package network import ( - "context" "fmt" "strings" "time" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" - clientset "k8s.io/client-go/kubernetes" - "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/e2e/framework" - imageutils "k8s.io/kubernetes/test/utils/image" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) const dnsTestPodHostName = "dns-querier-1" const dnsTestServiceName = "dns-test-service" -func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd string) *v1.Pod { - dnsPod := &v1.Pod{ - TypeMeta: metav1.TypeMeta{ - Kind: "Pod", - APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), - }, - ObjectMeta: metav1.ObjectMeta{ - Name: "dns-test-" + string(uuid.NewUUID()), - Namespace: namespace, - }, - Spec: v1.PodSpec{ - Volumes: []v1.Volume{ - { - Name: "results", - VolumeSource: v1.VolumeSource{ - EmptyDir: &v1.EmptyDirVolumeSource{}, - }, - }, - }, - Containers: []v1.Container{ - // TODO: Consider scraping logs instead of running a webserver. - { - Name: "webserver", - Image: imageutils.GetE2EImage(imageutils.TestWebserver), - Ports: []v1.ContainerPort{ - { - Name: "http", - ContainerPort: 80, - }, - }, - VolumeMounts: []v1.VolumeMount{ - { - Name: "results", - MountPath: "/results", - }, - }, - }, - { - Name: "querier", - Image: imageutils.GetE2EImage(imageutils.Dnsutils), - Command: []string{"sh", "-c", wheezyProbeCmd}, - VolumeMounts: []v1.VolumeMount{ - { - Name: "results", - MountPath: "/results", - }, - }, - }, - { - Name: "jessie-querier", - Image: imageutils.GetE2EImage(imageutils.JessieDnsutils), - Command: []string{"sh", "-c", jessieProbeCmd}, - VolumeMounts: []v1.VolumeMount{ - { - Name: "results", - MountPath: "/results", - }, - }, - }, - }, - }, - } - - dnsPod.Spec.Hostname = dnsTestPodHostName - dnsPod.Spec.Subdomain = dnsTestServiceName - - return dnsPod -} - -func createProbeCommand(namesToResolve []string, hostEntries []string, ptrLookupIP string, fileNamePrefix, namespace string) (string, []string) { - fileNames := make([]string, 0, len(namesToResolve)*2) - probeCmd := "for i in `seq 1 600`; do " - for _, name := range namesToResolve { - // Resolve by TCP and UDP DNS. Use $$(...) because $(...) is - // expanded by kubernetes (though this won't expand so should - // remain a literal, safe > sorry). - lookup := "A" - if strings.HasPrefix(name, "_") { - lookup = "SRV" - } - fileName := fmt.Sprintf("%s_udp@%s", fileNamePrefix, name) - fileNames = append(fileNames, fileName) - probeCmd += fmt.Sprintf(`test -n "$$(dig +notcp +noall +answer +search %s %s)" && echo OK > /results/%s;`, name, lookup, fileName) - fileName = fmt.Sprintf("%s_tcp@%s", fileNamePrefix, name) - fileNames = append(fileNames, fileName) - probeCmd += fmt.Sprintf(`test -n "$$(dig +tcp +noall +answer +search %s %s)" && echo OK > /results/%s;`, name, lookup, fileName) - } - - for _, name := range hostEntries { - fileName := fmt.Sprintf("%s_hosts@%s", fileNamePrefix, name) - fileNames = append(fileNames, fileName) - probeCmd += fmt.Sprintf(`test -n "$$(getent hosts %s)" && echo OK > /results/%s;`, name, fileName) - } - - podARecByUDPFileName := fmt.Sprintf("%s_udp@PodARecord", fileNamePrefix) - podARecByTCPFileName := fmt.Sprintf("%s_tcp@PodARecord", fileNamePrefix) - probeCmd += fmt.Sprintf(`podARec=$$(hostname -i| awk -F. '{print $$1"-"$$2"-"$$3"-"$$4".%s.pod.cluster.local"}');`, namespace) - probeCmd += fmt.Sprintf(`test -n "$$(dig +notcp +noall +answer +search $${podARec} A)" && echo OK > /results/%s;`, podARecByUDPFileName) - probeCmd += fmt.Sprintf(`test -n "$$(dig +tcp +noall +answer +search $${podARec} A)" && echo OK > /results/%s;`, podARecByTCPFileName) - fileNames = append(fileNames, podARecByUDPFileName) - fileNames = append(fileNames, podARecByTCPFileName) - - if len(ptrLookupIP) > 0 { - ptrLookup := fmt.Sprintf("%s.in-addr.arpa.", strings.Join(reverseArray(strings.Split(ptrLookupIP, ".")), ".")) - ptrRecByUDPFileName := fmt.Sprintf("%s_udp@PTR", ptrLookupIP) - ptrRecByTCPFileName := fmt.Sprintf("%s_tcp@PTR", ptrLookupIP) - probeCmd += fmt.Sprintf(`test -n "$$(dig +notcp +noall +answer +search %s PTR)" && echo OK > /results/%s;`, ptrLookup, ptrRecByUDPFileName) - probeCmd += fmt.Sprintf(`test -n "$$(dig +tcp +noall +answer +search %s PTR)" && echo OK > /results/%s;`, ptrLookup, ptrRecByTCPFileName) - fileNames = append(fileNames, ptrRecByUDPFileName) - fileNames = append(fileNames, ptrRecByTCPFileName) - } - - probeCmd += "sleep 1; done" - return probeCmd, fileNames -} - -// createTargetedProbeCommand returns a command line that performs a DNS lookup for a specific record type -func createTargetedProbeCommand(nameToResolve string, lookup string, fileNamePrefix string) (string, string) { - fileName := fmt.Sprintf("%s_udp@%s", fileNamePrefix, nameToResolve) - probeCmd := fmt.Sprintf("dig +short +tries=12 +norecurse %s %s > /results/%s", nameToResolve, lookup, fileName) - return probeCmd, fileName -} - -func assertFilesExist(fileNames []string, fileDir string, pod *v1.Pod, client clientset.Interface) { - assertFilesContain(fileNames, fileDir, pod, client, false, "") -} - -func assertFilesContain(fileNames []string, fileDir string, pod *v1.Pod, client clientset.Interface, check bool, expected string) { - var failed []string - - framework.ExpectNoError(wait.Poll(time.Second*10, time.Second*600, func() (bool, error) { - failed = []string{} - - ctx, cancel := context.WithTimeout(context.Background(), framework.SingleCallTimeout) - defer cancel() - - for _, fileName := range fileNames { - contents, err := client.CoreV1().RESTClient().Get(). - Context(ctx). - Namespace(pod.Namespace). - Resource("pods"). - SubResource("proxy"). - Name(pod.Name). - Suffix(fileDir, fileName). - Do().Raw() - - if err != nil { - if ctx.Err() != nil { - framework.Failf("Unable to read %s from pod %s: %v", fileName, pod.Name, err) - } else { - framework.Logf("Unable to read %s from pod %s: %v", fileName, pod.Name, err) - } - failed = append(failed, fileName) - } else if check && strings.TrimSpace(string(contents)) != expected { - framework.Logf("File %s from pod %s contains '%s' instead of '%s'", fileName, pod.Name, string(contents), expected) - failed = append(failed, fileName) - } - } - if len(failed) == 0 { - return true, nil - } - framework.Logf("Lookups using %s failed for: %v\n", pod.Name, failed) - return false, nil - })) - Expect(len(failed)).To(Equal(0)) -} - -func validateDNSResults(f *framework.Framework, pod *v1.Pod, fileNames []string) { - By("submitting the pod to kubernetes") - podClient := f.ClientSet.CoreV1().Pods(f.Namespace.Name) - defer func() { - By("deleting the pod") - defer GinkgoRecover() - podClient.Delete(pod.Name, metav1.NewDeleteOptions(0)) - }() - if _, err := podClient.Create(pod); err != nil { - framework.Failf("Failed to create %s pod: %v", pod.Name, err) - } - - framework.ExpectNoError(f.WaitForPodRunning(pod.Name)) - - By("retrieving the pod") - pod, err := podClient.Get(pod.Name, metav1.GetOptions{}) - if err != nil { - framework.Failf("Failed to get pod %s: %v", pod.Name, err) - } - // Try to find results for each expected name. - By("looking for the results for each expected name from probers") - assertFilesExist(fileNames, "results", pod, f.ClientSet) - - // TODO: probe from the host, too. - - framework.Logf("DNS probes using %s succeeded\n", pod.Name) -} - -func validateTargetedProbeOutput(f *framework.Framework, pod *v1.Pod, fileNames []string, value string) { - By("submitting the pod to kubernetes") - podClient := f.ClientSet.CoreV1().Pods(f.Namespace.Name) - defer func() { - By("deleting the pod") - defer GinkgoRecover() - podClient.Delete(pod.Name, metav1.NewDeleteOptions(0)) - }() - if _, err := podClient.Create(pod); err != nil { - framework.Failf("Failed to create %s pod: %v", pod.Name, err) - } - - framework.ExpectNoError(f.WaitForPodRunning(pod.Name)) - - By("retrieving the pod") - pod, err := podClient.Get(pod.Name, metav1.GetOptions{}) - if err != nil { - framework.Failf("Failed to get pod %s: %v", pod.Name, err) - } - // Try to find the expected value for each expected name. - By("looking for the results for each expected name from probers") - assertFilesContain(fileNames, "results", pod, f.ClientSet, true, value) - - framework.Logf("DNS probes using %s succeeded\n", pod.Name) -} - -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 -} - var _ = SIGDescribe("DNS", func() { f := framework.NewDefaultFramework("dns") @@ -295,7 +62,7 @@ var _ = SIGDescribe("DNS", func() { // Run a pod which probes DNS and exposes the results by HTTP. By("creating a pod to probe DNS") - pod := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd) + pod := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, dnsTestPodHostName, dnsTestServiceName) validateDNSResults(f, pod, append(wheezyFileNames, jessieFileNames...)) }) @@ -345,7 +112,7 @@ var _ = SIGDescribe("DNS", func() { // Run a pod which probes DNS and exposes the results by HTTP. By("creating a pod to probe DNS") - pod := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd) + pod := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, dnsTestPodHostName, dnsTestServiceName) pod.ObjectMeta.Labels = testServiceSelector validateDNSResults(f, pod, append(wheezyFileNames, jessieFileNames...)) @@ -378,7 +145,7 @@ var _ = SIGDescribe("DNS", func() { // Run a pod which probes DNS and exposes the results by HTTP. By("creating a pod to probe DNS") - pod1 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd) + pod1 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, dnsTestPodHostName, dnsTestServiceName) pod1.ObjectMeta.Labels = testServiceSelector pod1.Spec.Hostname = podHostname pod1.Spec.Subdomain = serviceName @@ -407,7 +174,7 @@ var _ = SIGDescribe("DNS", func() { // Run a pod which probes DNS and exposes the results by HTTP. By("creating a pod to probe DNS") - pod1 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd) + pod1 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, dnsTestPodHostName, dnsTestServiceName) validateTargetedProbeOutput(f, pod1, []string{wheezyFileName, jessieFileName}, "foo.example.com.") @@ -424,7 +191,7 @@ var _ = SIGDescribe("DNS", func() { // Run a pod which probes DNS and exposes the results by HTTP. By("creating a second pod to probe DNS") - pod2 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd) + pod2 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, dnsTestPodHostName, dnsTestServiceName) validateTargetedProbeOutput(f, pod2, []string{wheezyFileName, jessieFileName}, "bar.example.com.") @@ -444,11 +211,111 @@ var _ = SIGDescribe("DNS", func() { // Run a pod which probes DNS and exposes the results by HTTP. By("creating a third pod to probe DNS") - pod3 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd) + pod3 := createDNSPod(f.Namespace.Name, wheezyProbeCmd, jessieProbeCmd, dnsTestPodHostName, dnsTestServiceName) svc, err := f.ClientSet.CoreV1().Services(f.Namespace.Name).Get(externalNameService.Name, metav1.GetOptions{}) Expect(err).NotTo(HaveOccurred()) validateTargetedProbeOutput(f, pod3, []string{wheezyFileName, jessieFileName}, svc.Spec.ClusterIP) }) + + It("should support configurable pod resolv.conf", func() { + By("Preparing a test DNS service with injected DNS names...") + testInjectedIP := "1.1.1.1" + testDNSNameShort := "notexistname" + testSearchPath := "resolv.conf.local" + testDNSNameFull := fmt.Sprintf("%s.%s", testDNSNameShort, testSearchPath) + + testServerPod := generateDNSServerPod(map[string]string{ + testDNSNameFull: testInjectedIP, + }) + testServerPod, err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(testServerPod) + Expect(err).NotTo(HaveOccurred(), "failed to create pod %s", testServerPod.Name) + framework.Logf("Created pod %v", testServerPod) + defer func() { + framework.Logf("Deleting pod %s...", testServerPod.Name) + if err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(testServerPod.Name, metav1.NewDeleteOptions(0)); err != nil { + framework.Failf("Failed to delete pod %s: %v", testServerPod.Name, err) + } + }() + Expect(f.WaitForPodRunning(testServerPod.Name)).NotTo(HaveOccurred(), "failed to wait for pod %s to be running", testServerPod.Name) + + // Retrieve server pod IP. + testServerPod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Get(testServerPod.Name, metav1.GetOptions{}) + Expect(err).NotTo(HaveOccurred(), "failed to get pod %v", testServerPod.Name) + testServerIP := testServerPod.Status.PodIP + framework.Logf("testServerIP is %s", testServerIP) + + By("Creating a pod with dnsPolicy=None and customized dnsConfig...") + testUtilsPod := generateDNSUtilsPod() + testUtilsPod.Spec.DNSPolicy = v1.DNSNone + testNdotsValue := "2" + testUtilsPod.Spec.DNSConfig = &v1.PodDNSConfig{ + Nameservers: []string{testServerIP}, + Searches: []string{testSearchPath}, + Options: []v1.PodDNSConfigOption{ + { + Name: "ndots", + Value: &testNdotsValue, + }, + }, + } + testUtilsPod, err = f.ClientSet.CoreV1().Pods(f.Namespace.Name).Create(testUtilsPod) + Expect(err).NotTo(HaveOccurred(), "failed to create pod %s", testUtilsPod.Name) + framework.Logf("Created pod %v", testUtilsPod) + defer func() { + framework.Logf("Deleting pod %s...", testUtilsPod.Name) + if err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(testUtilsPod.Name, metav1.NewDeleteOptions(0)); err != nil { + framework.Failf("Failed to delete pod %s: %v", testUtilsPod.Name, err) + } + }() + Expect(f.WaitForPodRunning(testUtilsPod.Name)).NotTo(HaveOccurred(), "failed to wait for pod %s to be running", testUtilsPod.Name) + + By("Verifying customized DNS option is configured on pod...") + // TODO: Figure out a better way other than checking the actual resolv,conf file. + cmd := []string{"cat", "/etc/resolv.conf"} + stdout, stderr, err := f.ExecWithOptions(framework.ExecOptions{ + Command: cmd, + Namespace: f.Namespace.Name, + PodName: testUtilsPod.Name, + ContainerName: "util", + CaptureStdout: true, + CaptureStderr: true, + }) + Expect(err).NotTo(HaveOccurred(), "failed to examine resolv,conf file on pod, stdout: %v, stderr: %v, err: %v", stdout, stderr, err) + if !strings.Contains(stdout, "ndots:2") { + framework.Failf("customized DNS options not found in resolv.conf, got: %s", stdout) + } + + By("Verifying customized name server and search path are working...") + // Do dig on not-exist-dns-name and see if the injected DNS record is returned. + // This verifies both: + // - Custom search path is appended. + // - DNS query is sent to the specified server. + cmd = []string{"/usr/bin/dig", "+short", "+search", testDNSNameShort} + digFunc := func() (bool, error) { + stdout, stderr, err := f.ExecWithOptions(framework.ExecOptions{ + Command: cmd, + Namespace: f.Namespace.Name, + PodName: testUtilsPod.Name, + ContainerName: "util", + CaptureStdout: true, + CaptureStderr: true, + }) + if err != nil { + framework.Logf("Failed to execute dig command, stdout:%v, stderr: %v, err: %v", stdout, stderr, err) + return false, nil + } + res := strings.Split(stdout, "\n") + if len(res) != 1 || res[0] != testInjectedIP { + framework.Logf("Expect command `%v` to return %s, got: %v", cmd, testInjectedIP, res) + return false, nil + } + return true, nil + } + err = wait.PollImmediate(5*time.Second, 3*time.Minute, digFunc) + Expect(err).NotTo(HaveOccurred(), "failed to verify customized name server and search path") + + // TODO: Add more test cases for other DNSPolicies. + }) }) diff --git a/test/e2e/network/dns_common.go b/test/e2e/network/dns_common.go index 66ecefa9da2..1400f42e0ed 100644 --- a/test/e2e/network/dns_common.go +++ b/test/e2e/network/dns_common.go @@ -17,6 +17,7 @@ limitations under the License. package network import ( + "context" "fmt" "strings" "time" @@ -27,8 +28,10 @@ import ( "k8s.io/apimachinery/pkg/fields" "k8s.io/apimachinery/pkg/labels" "k8s.io/apimachinery/pkg/util/intstr" + "k8s.io/apimachinery/pkg/util/uuid" "k8s.io/apimachinery/pkg/util/wait" clientset "k8s.io/client-go/kubernetes" + "k8s.io/kubernetes/pkg/api/testapi" "k8s.io/kubernetes/test/e2e/framework" imageutils "k8s.io/kubernetes/test/utils/image" @@ -229,13 +232,12 @@ func (t *dnsTestCommon) deleteUtilPod() { } } -func (t *dnsTestCommon) createDNSServer(aRecords map[string]string) { - t.dnsServerPod = &v1.Pod{ +func generateDNSServerPod(aRecords map[string]string) *v1.Pod { + pod := &v1.Pod{ TypeMeta: metav1.TypeMeta{ Kind: "Pod", }, ObjectMeta: metav1.ObjectMeta{ - Namespace: t.f.Namespace.Name, GenerateName: "e2e-dns-configmap-dns-server-", }, Spec: v1.PodSpec{ @@ -257,10 +259,15 @@ func (t *dnsTestCommon) createDNSServer(aRecords map[string]string) { } for name, ip := range aRecords { - t.dnsServerPod.Spec.Containers[0].Command = append( - t.dnsServerPod.Spec.Containers[0].Command, + pod.Spec.Containers[0].Command = append( + pod.Spec.Containers[0].Command, fmt.Sprintf("-A/%v/%v", name, ip)) } + return pod +} + +func (t *dnsTestCommon) createDNSServer(aRecords map[string]string) { + t.dnsServerPod = generateDNSServerPod(aRecords) var err error t.dnsServerPod, err = t.c.CoreV1().Pods(t.f.Namespace.Name).Create(t.dnsServerPod) @@ -280,3 +287,252 @@ func (t *dnsTestCommon) deleteDNSServerPod() { t.utilPod.Namespace, t.dnsServerPod.Name, err) } } + +func createDNSPod(namespace, wheezyProbeCmd, jessieProbeCmd, podHostName, serviceName string) *v1.Pod { + dnsPod := &v1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + APIVersion: testapi.Groups[v1.GroupName].GroupVersion().String(), + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "dns-test-" + string(uuid.NewUUID()), + Namespace: namespace, + }, + Spec: v1.PodSpec{ + Volumes: []v1.Volume{ + { + Name: "results", + VolumeSource: v1.VolumeSource{ + EmptyDir: &v1.EmptyDirVolumeSource{}, + }, + }, + }, + Containers: []v1.Container{ + // TODO: Consider scraping logs instead of running a webserver. + { + Name: "webserver", + Image: imageutils.GetE2EImage(imageutils.TestWebserver), + Ports: []v1.ContainerPort{ + { + Name: "http", + ContainerPort: 80, + }, + }, + VolumeMounts: []v1.VolumeMount{ + { + Name: "results", + MountPath: "/results", + }, + }, + }, + { + Name: "querier", + Image: imageutils.GetE2EImage(imageutils.Dnsutils), + Command: []string{"sh", "-c", wheezyProbeCmd}, + VolumeMounts: []v1.VolumeMount{ + { + Name: "results", + MountPath: "/results", + }, + }, + }, + { + Name: "jessie-querier", + Image: imageutils.GetE2EImage(imageutils.JessieDnsutils), + Command: []string{"sh", "-c", jessieProbeCmd}, + VolumeMounts: []v1.VolumeMount{ + { + Name: "results", + MountPath: "/results", + }, + }, + }, + }, + }, + } + + dnsPod.Spec.Hostname = podHostName + dnsPod.Spec.Subdomain = serviceName + + return dnsPod +} + +func createProbeCommand(namesToResolve []string, hostEntries []string, ptrLookupIP string, fileNamePrefix, namespace string) (string, []string) { + fileNames := make([]string, 0, len(namesToResolve)*2) + probeCmd := "for i in `seq 1 600`; do " + for _, name := range namesToResolve { + // Resolve by TCP and UDP DNS. Use $$(...) because $(...) is + // expanded by kubernetes (though this won't expand so should + // remain a literal, safe > sorry). + lookup := "A" + if strings.HasPrefix(name, "_") { + lookup = "SRV" + } + fileName := fmt.Sprintf("%s_udp@%s", fileNamePrefix, name) + fileNames = append(fileNames, fileName) + probeCmd += fmt.Sprintf(`test -n "$$(dig +notcp +noall +answer +search %s %s)" && echo OK > /results/%s;`, name, lookup, fileName) + fileName = fmt.Sprintf("%s_tcp@%s", fileNamePrefix, name) + fileNames = append(fileNames, fileName) + probeCmd += fmt.Sprintf(`test -n "$$(dig +tcp +noall +answer +search %s %s)" && echo OK > /results/%s;`, name, lookup, fileName) + } + + for _, name := range hostEntries { + fileName := fmt.Sprintf("%s_hosts@%s", fileNamePrefix, name) + fileNames = append(fileNames, fileName) + probeCmd += fmt.Sprintf(`test -n "$$(getent hosts %s)" && echo OK > /results/%s;`, name, fileName) + } + + podARecByUDPFileName := fmt.Sprintf("%s_udp@PodARecord", fileNamePrefix) + podARecByTCPFileName := fmt.Sprintf("%s_tcp@PodARecord", fileNamePrefix) + probeCmd += fmt.Sprintf(`podARec=$$(hostname -i| awk -F. '{print $$1"-"$$2"-"$$3"-"$$4".%s.pod.cluster.local"}');`, namespace) + probeCmd += fmt.Sprintf(`test -n "$$(dig +notcp +noall +answer +search $${podARec} A)" && echo OK > /results/%s;`, podARecByUDPFileName) + probeCmd += fmt.Sprintf(`test -n "$$(dig +tcp +noall +answer +search $${podARec} A)" && echo OK > /results/%s;`, podARecByTCPFileName) + fileNames = append(fileNames, podARecByUDPFileName) + fileNames = append(fileNames, podARecByTCPFileName) + + if len(ptrLookupIP) > 0 { + ptrLookup := fmt.Sprintf("%s.in-addr.arpa.", strings.Join(reverseArray(strings.Split(ptrLookupIP, ".")), ".")) + ptrRecByUDPFileName := fmt.Sprintf("%s_udp@PTR", ptrLookupIP) + ptrRecByTCPFileName := fmt.Sprintf("%s_tcp@PTR", ptrLookupIP) + probeCmd += fmt.Sprintf(`test -n "$$(dig +notcp +noall +answer +search %s PTR)" && echo OK > /results/%s;`, ptrLookup, ptrRecByUDPFileName) + probeCmd += fmt.Sprintf(`test -n "$$(dig +tcp +noall +answer +search %s PTR)" && echo OK > /results/%s;`, ptrLookup, ptrRecByTCPFileName) + fileNames = append(fileNames, ptrRecByUDPFileName) + fileNames = append(fileNames, ptrRecByTCPFileName) + } + + probeCmd += "sleep 1; done" + return probeCmd, fileNames +} + +// createTargetedProbeCommand returns a command line that performs a DNS lookup for a specific record type +func createTargetedProbeCommand(nameToResolve string, lookup string, fileNamePrefix string) (string, string) { + fileName := fmt.Sprintf("%s_udp@%s", fileNamePrefix, nameToResolve) + probeCmd := fmt.Sprintf("dig +short +tries=12 +norecurse %s %s > /results/%s", nameToResolve, lookup, fileName) + return probeCmd, fileName +} + +func assertFilesExist(fileNames []string, fileDir string, pod *v1.Pod, client clientset.Interface) { + assertFilesContain(fileNames, fileDir, pod, client, false, "") +} + +func assertFilesContain(fileNames []string, fileDir string, pod *v1.Pod, client clientset.Interface, check bool, expected string) { + var failed []string + + framework.ExpectNoError(wait.Poll(time.Second*10, time.Second*600, func() (bool, error) { + failed = []string{} + + ctx, cancel := context.WithTimeout(context.Background(), framework.SingleCallTimeout) + defer cancel() + + for _, fileName := range fileNames { + contents, err := client.CoreV1().RESTClient().Get(). + Context(ctx). + Namespace(pod.Namespace). + Resource("pods"). + SubResource("proxy"). + Name(pod.Name). + Suffix(fileDir, fileName). + Do().Raw() + + if err != nil { + if ctx.Err() != nil { + framework.Failf("Unable to read %s from pod %s: %v", fileName, pod.Name, err) + } else { + framework.Logf("Unable to read %s from pod %s: %v", fileName, pod.Name, err) + } + failed = append(failed, fileName) + } else if check && strings.TrimSpace(string(contents)) != expected { + framework.Logf("File %s from pod %s contains '%s' instead of '%s'", fileName, pod.Name, string(contents), expected) + failed = append(failed, fileName) + } + } + if len(failed) == 0 { + return true, nil + } + framework.Logf("Lookups using %s failed for: %v\n", pod.Name, failed) + return false, nil + })) + Expect(len(failed)).To(Equal(0)) +} + +func validateDNSResults(f *framework.Framework, pod *v1.Pod, fileNames []string) { + By("submitting the pod to kubernetes") + podClient := f.ClientSet.CoreV1().Pods(f.Namespace.Name) + defer func() { + By("deleting the pod") + defer GinkgoRecover() + podClient.Delete(pod.Name, metav1.NewDeleteOptions(0)) + }() + if _, err := podClient.Create(pod); err != nil { + framework.Failf("Failed to create %s pod: %v", pod.Name, err) + } + + framework.ExpectNoError(f.WaitForPodRunning(pod.Name)) + + By("retrieving the pod") + pod, err := podClient.Get(pod.Name, metav1.GetOptions{}) + if err != nil { + framework.Failf("Failed to get pod %s: %v", pod.Name, err) + } + // Try to find results for each expected name. + By("looking for the results for each expected name from probers") + assertFilesExist(fileNames, "results", pod, f.ClientSet) + + // TODO: probe from the host, too. + + framework.Logf("DNS probes using %s succeeded\n", pod.Name) +} + +func validateTargetedProbeOutput(f *framework.Framework, pod *v1.Pod, fileNames []string, value string) { + By("submitting the pod to kubernetes") + podClient := f.ClientSet.CoreV1().Pods(f.Namespace.Name) + defer func() { + By("deleting the pod") + defer GinkgoRecover() + podClient.Delete(pod.Name, metav1.NewDeleteOptions(0)) + }() + if _, err := podClient.Create(pod); err != nil { + framework.Failf("Failed to create %s pod: %v", pod.Name, err) + } + + framework.ExpectNoError(f.WaitForPodRunning(pod.Name)) + + By("retrieving the pod") + pod, err := podClient.Get(pod.Name, metav1.GetOptions{}) + if err != nil { + framework.Failf("Failed to get pod %s: %v", pod.Name, err) + } + // Try to find the expected value for each expected name. + By("looking for the results for each expected name from probers") + assertFilesContain(fileNames, "results", pod, f.ClientSet, true, value) + + framework.Logf("DNS probes using %s succeeded\n", pod.Name) +} + +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 +} + +func generateDNSUtilsPod() *v1.Pod { + return &v1.Pod{ + TypeMeta: metav1.TypeMeta{ + Kind: "Pod", + }, + ObjectMeta: metav1.ObjectMeta{ + GenerateName: "e2e-dns-utils-", + }, + Spec: v1.PodSpec{ + Containers: []v1.Container{ + { + Name: "util", + Image: imageutils.GetE2EImage(imageutils.Dnsutils), + Command: []string{"sleep", "10000"}, + }, + }, + }, + } +}