mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-20 10:20:51 +00:00
Revert "Field status.hostIPs
added for Pod (#101566)"
This reverts commit 61b3c028ba
.
This commit is contained in:
parent
e54ff8a7ff
commit
1108bed763
28
api/openapi-spec/swagger.json
generated
28
api/openapi-spec/swagger.json
generated
@ -6720,16 +6720,6 @@
|
|||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"io.k8s.api.core.v1.HostIP": {
|
|
||||||
"description": "HostIP address information for entries in the (plural) HostIPs field.",
|
|
||||||
"properties": {
|
|
||||||
"ip": {
|
|
||||||
"description": "IP is the IP address assigned to the host",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"io.k8s.api.core.v1.HostPathVolumeSource": {
|
"io.k8s.api.core.v1.HostPathVolumeSource": {
|
||||||
"description": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.",
|
"description": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -8396,10 +8386,10 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"io.k8s.api.core.v1.PodIP": {
|
"io.k8s.api.core.v1.PodIP": {
|
||||||
"description": "PodIP address information for entries in the (plural) PodIPs field.",
|
"description": "IP address information for entries in the (plural) PodIPs field. Each entry includes:\n IP: An IP address allocated to the pod. Routable at least within the cluster.",
|
||||||
"properties": {
|
"properties": {
|
||||||
"ip": {
|
"ip": {
|
||||||
"description": "IP is the IP address assigned to the pod",
|
"description": "ip is an IP address (IPv4 or IPv6) assigned to the pod",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -8769,19 +8759,9 @@
|
|||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"hostIP": {
|
"hostIP": {
|
||||||
"description": "hostIP holds the IP address of the host to which the pod is assigned. Empty if the pod has not started yet. A pod can be assigned to a node that has a problem in kubelet which in turns mean that HostIP will not be updated even if there is node is assigned to pod",
|
"description": "IP address of the host to which the pod is assigned. Empty if not yet scheduled.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"hostIPs": {
|
|
||||||
"description": "hostIPs holds the IP addresses allocated to the host. If this field is specified, the first entry must match the hostIP field. This list is empty if the pod has not started yet. A pod can be assigned to a node that has a problem in kubelet which in turns means that HostIPs will not be updated even if there is a node is assigned to this pod.",
|
|
||||||
"items": {
|
|
||||||
"$ref": "#/definitions/io.k8s.api.core.v1.HostIP"
|
|
||||||
},
|
|
||||||
"type": "array",
|
|
||||||
"x-kubernetes-list-type": "set",
|
|
||||||
"x-kubernetes-patch-merge-key": "ip",
|
|
||||||
"x-kubernetes-patch-strategy": "merge"
|
|
||||||
},
|
|
||||||
"initContainerStatuses": {
|
"initContainerStatuses": {
|
||||||
"description": "The list has one entry per init container in the manifest. The most recent successful init container will have ready = true, the most recently started container will have startTime set. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status",
|
"description": "The list has one entry per init container in the manifest. The most recent successful init container will have ready = true, the most recently started container will have startTime set. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status",
|
||||||
"items": {
|
"items": {
|
||||||
@ -8809,7 +8789,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"podIP": {
|
"podIP": {
|
||||||
"description": "podIP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.",
|
"description": "IP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"podIPs": {
|
"podIPs": {
|
||||||
|
@ -2609,16 +2609,6 @@
|
|||||||
},
|
},
|
||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"io.k8s.api.core.v1.HostIP": {
|
|
||||||
"description": "HostIP address information for entries in the (plural) HostIPs field.",
|
|
||||||
"properties": {
|
|
||||||
"ip": {
|
|
||||||
"description": "IP is the IP address assigned to the host",
|
|
||||||
"type": "string"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"type": "object"
|
|
||||||
},
|
|
||||||
"io.k8s.api.core.v1.HostPathVolumeSource": {
|
"io.k8s.api.core.v1.HostPathVolumeSource": {
|
||||||
"description": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.",
|
"description": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.",
|
||||||
"properties": {
|
"properties": {
|
||||||
@ -4854,10 +4844,10 @@
|
|||||||
"type": "object"
|
"type": "object"
|
||||||
},
|
},
|
||||||
"io.k8s.api.core.v1.PodIP": {
|
"io.k8s.api.core.v1.PodIP": {
|
||||||
"description": "PodIP address information for entries in the (plural) PodIPs field.",
|
"description": "IP address information for entries in the (plural) PodIPs field. Each entry includes:\n IP: An IP address allocated to the pod. Routable at least within the cluster.",
|
||||||
"properties": {
|
"properties": {
|
||||||
"ip": {
|
"ip": {
|
||||||
"description": "IP is the IP address assigned to the pod",
|
"description": "ip is an IP address (IPv4 or IPv6) assigned to the pod",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -5339,24 +5329,9 @@
|
|||||||
"type": "array"
|
"type": "array"
|
||||||
},
|
},
|
||||||
"hostIP": {
|
"hostIP": {
|
||||||
"description": "hostIP holds the IP address of the host to which the pod is assigned. Empty if the pod has not started yet. A pod can be assigned to a node that has a problem in kubelet which in turns mean that HostIP will not be updated even if there is node is assigned to pod",
|
"description": "IP address of the host to which the pod is assigned. Empty if not yet scheduled.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"hostIPs": {
|
|
||||||
"description": "hostIPs holds the IP addresses allocated to the host. If this field is specified, the first entry must match the hostIP field. This list is empty if the pod has not started yet. A pod can be assigned to a node that has a problem in kubelet which in turns means that HostIPs will not be updated even if there is a node is assigned to this pod.",
|
|
||||||
"items": {
|
|
||||||
"allOf": [
|
|
||||||
{
|
|
||||||
"$ref": "#/components/schemas/io.k8s.api.core.v1.HostIP"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"default": {}
|
|
||||||
},
|
|
||||||
"type": "array",
|
|
||||||
"x-kubernetes-list-type": "set",
|
|
||||||
"x-kubernetes-patch-merge-key": "ip",
|
|
||||||
"x-kubernetes-patch-strategy": "merge"
|
|
||||||
},
|
|
||||||
"initContainerStatuses": {
|
"initContainerStatuses": {
|
||||||
"description": "The list has one entry per init container in the manifest. The most recent successful init container will have ready = true, the most recently started container will have startTime set. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status",
|
"description": "The list has one entry per init container in the manifest. The most recent successful init container will have ready = true, the most recently started container will have startTime set. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status",
|
||||||
"items": {
|
"items": {
|
||||||
@ -5389,7 +5364,7 @@
|
|||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"podIP": {
|
"podIP": {
|
||||||
"description": "podIP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.",
|
"description": "IP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.",
|
||||||
"type": "string"
|
"type": "string"
|
||||||
},
|
},
|
||||||
"podIPs": {
|
"podIPs": {
|
||||||
|
@ -434,8 +434,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po
|
|||||||
AllowExpandedDNSConfig: utilfeature.DefaultFeatureGate.Enabled(features.ExpandedDNSConfig) || haveSameExpandedDNSConfig(podSpec, oldPodSpec),
|
AllowExpandedDNSConfig: utilfeature.DefaultFeatureGate.Enabled(features.ExpandedDNSConfig) || haveSameExpandedDNSConfig(podSpec, oldPodSpec),
|
||||||
// Allow pod spec to use OS field
|
// Allow pod spec to use OS field
|
||||||
AllowOSField: utilfeature.DefaultFeatureGate.Enabled(features.IdentifyPodOS),
|
AllowOSField: utilfeature.DefaultFeatureGate.Enabled(features.IdentifyPodOS),
|
||||||
// Allow pod spec to use status.hostIPs in downward API if feature is enabled
|
|
||||||
AllowHostIPsField: utilfeature.DefaultFeatureGate.Enabled(features.PodHostIPs),
|
|
||||||
// The default sysctl value does not contain a forward slash, and in 1.24 we intend to relax this to be true by default
|
// The default sysctl value does not contain a forward slash, and in 1.24 we intend to relax this to be true by default
|
||||||
AllowSysctlRegexContainSlash: false,
|
AllowSysctlRegexContainSlash: false,
|
||||||
}
|
}
|
||||||
@ -456,9 +454,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po
|
|||||||
// if old spec has OS field set, we must allow it
|
// if old spec has OS field set, we must allow it
|
||||||
opts.AllowOSField = opts.AllowOSField || oldPodSpec.OS != nil
|
opts.AllowOSField = opts.AllowOSField || oldPodSpec.OS != nil
|
||||||
|
|
||||||
// if old spec has status.hostIPs downwardAPI set, we must allow it
|
|
||||||
opts.AllowHostIPsField = opts.AllowHostIPsField || hasUsedDownwardAPIFieldPathWithPodSpec(oldPodSpec, "status.hostIPs")
|
|
||||||
|
|
||||||
// if old spec used non-integer multiple of huge page unit size, we must allow it
|
// if old spec used non-integer multiple of huge page unit size, we must allow it
|
||||||
opts.AllowIndivisibleHugePagesValues = usesIndivisibleHugePagesValues(oldPodSpec)
|
opts.AllowIndivisibleHugePagesValues = usesIndivisibleHugePagesValues(oldPodSpec)
|
||||||
|
|
||||||
@ -475,57 +470,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po
|
|||||||
return opts
|
return opts
|
||||||
}
|
}
|
||||||
|
|
||||||
func hasUsedDownwardAPIFieldPathWithPodSpec(podSpec *api.PodSpec, fieldPath string) bool {
|
|
||||||
if podSpec == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, vol := range podSpec.Volumes {
|
|
||||||
if hasUsedDownwardAPIFieldPathWithVolume(&vol, fieldPath) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, c := range podSpec.InitContainers {
|
|
||||||
if hasUsedDownwardAPIFieldPathWithContainer(&c, fieldPath) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for _, c := range podSpec.Containers {
|
|
||||||
if hasUsedDownwardAPIFieldPathWithContainer(&c, fieldPath) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasUsedDownwardAPIFieldPathWithVolume(volume *api.Volume, fieldPath string) bool {
|
|
||||||
if volume == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
if volume.DownwardAPI != nil {
|
|
||||||
for _, file := range volume.DownwardAPI.Items {
|
|
||||||
if file.FieldRef != nil &&
|
|
||||||
file.FieldRef.FieldPath == fieldPath {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func hasUsedDownwardAPIFieldPathWithContainer(container *api.Container, fieldPath string) bool {
|
|
||||||
if container == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
for _, env := range container.Env {
|
|
||||||
if env.ValueFrom != nil &&
|
|
||||||
env.ValueFrom.FieldRef != nil &&
|
|
||||||
env.ValueFrom.FieldRef.FieldPath == fieldPath {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetValidationOptionsFromPodTemplate will return pod validation options for specified template.
|
// GetValidationOptionsFromPodTemplate will return pod validation options for specified template.
|
||||||
func GetValidationOptionsFromPodTemplate(podTemplate, oldPodTemplate *api.PodTemplateSpec) apivalidation.PodValidationOptions {
|
func GetValidationOptionsFromPodTemplate(podTemplate, oldPodTemplate *api.PodTemplateSpec) apivalidation.PodValidationOptions {
|
||||||
var newPodSpec, oldPodSpec *api.PodSpec
|
var newPodSpec, oldPodSpec *api.PodSpec
|
||||||
@ -568,39 +512,19 @@ func DropDisabledTemplateFields(podTemplate, oldPodTemplate *api.PodTemplateSpec
|
|||||||
func DropDisabledPodFields(pod, oldPod *api.Pod) {
|
func DropDisabledPodFields(pod, oldPod *api.Pod) {
|
||||||
var (
|
var (
|
||||||
podSpec *api.PodSpec
|
podSpec *api.PodSpec
|
||||||
podStatus *api.PodStatus
|
|
||||||
podAnnotations map[string]string
|
podAnnotations map[string]string
|
||||||
oldPodSpec *api.PodSpec
|
oldPodSpec *api.PodSpec
|
||||||
oldPodStatus *api.PodStatus
|
|
||||||
oldPodAnnotations map[string]string
|
oldPodAnnotations map[string]string
|
||||||
)
|
)
|
||||||
if pod != nil {
|
if pod != nil {
|
||||||
podSpec = &pod.Spec
|
podSpec = &pod.Spec
|
||||||
podAnnotations = pod.Annotations
|
podAnnotations = pod.Annotations
|
||||||
podStatus = &pod.Status
|
|
||||||
}
|
}
|
||||||
if oldPod != nil {
|
if oldPod != nil {
|
||||||
oldPodSpec = &oldPod.Spec
|
oldPodSpec = &oldPod.Spec
|
||||||
oldPodAnnotations = oldPod.Annotations
|
oldPodAnnotations = oldPod.Annotations
|
||||||
oldPodStatus = &oldPod.Status
|
|
||||||
}
|
}
|
||||||
dropDisabledFields(podSpec, podAnnotations, oldPodSpec, oldPodAnnotations)
|
dropDisabledFields(podSpec, podAnnotations, oldPodSpec, oldPodAnnotations)
|
||||||
dropDisabledStatusFields(podStatus, oldPodStatus)
|
|
||||||
}
|
|
||||||
|
|
||||||
// dropDisabledStatusFields removes disabled fields from the pod status
|
|
||||||
func dropDisabledStatusFields(podStatus *api.PodStatus, oldPodStatus *api.PodStatus) {
|
|
||||||
// drop HostIPs to empty (disable PodHostIPs).
|
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.PodHostIPs) && !hostIPsInUse(oldPodStatus) {
|
|
||||||
podStatus.HostIPs = nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func hostIPsInUse(podStatus *api.PodStatus) bool {
|
|
||||||
if podStatus == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
return len(podStatus.HostIPs) > 0
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dropDisabledFields removes disabled fields from the pod metadata and spec.
|
// dropDisabledFields removes disabled fields from the pod metadata and spec.
|
||||||
|
@ -1768,73 +1768,3 @@ func TestDropOSField(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDropDisabledStatusFields(t *testing.T) {
|
|
||||||
podWithHostIP := func() *api.PodStatus {
|
|
||||||
return &api.PodStatus{
|
|
||||||
HostIPs: makeHostIPs("10.0.0.1", "fd00:10::1"),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
podWithoutHostIPs := func() *api.PodStatus {
|
|
||||||
return &api.PodStatus{
|
|
||||||
HostIPs: nil,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
tests := []struct {
|
|
||||||
name string
|
|
||||||
podStatus *api.PodStatus
|
|
||||||
oldPodStatus *api.PodStatus
|
|
||||||
wantPodStatus *api.PodStatus
|
|
||||||
featureEnabled bool
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
podStatus: podWithHostIP(),
|
|
||||||
oldPodStatus: podWithHostIP(),
|
|
||||||
featureEnabled: false,
|
|
||||||
|
|
||||||
wantPodStatus: podWithHostIP(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
podStatus: podWithoutHostIPs(),
|
|
||||||
oldPodStatus: podWithHostIP(),
|
|
||||||
featureEnabled: true,
|
|
||||||
|
|
||||||
wantPodStatus: podWithoutHostIPs(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
podStatus: podWithoutHostIPs(),
|
|
||||||
oldPodStatus: podWithoutHostIPs(),
|
|
||||||
featureEnabled: false,
|
|
||||||
|
|
||||||
wantPodStatus: podWithoutHostIPs(),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
podStatus: podWithHostIP(),
|
|
||||||
oldPodStatus: podWithoutHostIPs(),
|
|
||||||
featureEnabled: true,
|
|
||||||
|
|
||||||
wantPodStatus: podWithHostIP(),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, tt := range tests {
|
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodHostIPs, tt.featureEnabled)()
|
|
||||||
|
|
||||||
dropDisabledStatusFields(tt.podStatus, tt.oldPodStatus)
|
|
||||||
|
|
||||||
if !reflect.DeepEqual(tt.podStatus, tt.wantPodStatus) {
|
|
||||||
t.Errorf("dropDisabledStatusFields() = %v, want %v", tt.podStatus, tt.wantPodStatus)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func makeHostIPs(ips ...string) []api.HostIP {
|
|
||||||
ret := []api.HostIP{}
|
|
||||||
for _, ip := range ips {
|
|
||||||
ret = append(ret, api.HostIP{IP: ip})
|
|
||||||
}
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
@ -91,10 +91,6 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
|
|||||||
s.EnableServiceLinks = &enableServiceLinks
|
s.EnableServiceLinks = &enableServiceLinks
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
func(s *core.PodStatus, c fuzz.Continue) {
|
|
||||||
c.Fuzz(&s)
|
|
||||||
s.HostIPs = []core.HostIP{{IP: s.HostIP}}
|
|
||||||
},
|
|
||||||
func(j *core.PodPhase, c fuzz.Continue) {
|
func(j *core.PodPhase, c fuzz.Continue) {
|
||||||
statuses := []core.PodPhase{core.PodPending, core.PodRunning, core.PodFailed, core.PodUnknown}
|
statuses := []core.PodPhase{core.PodPending, core.PodRunning, core.PodFailed, core.PodUnknown}
|
||||||
*j = statuses[c.Rand.Intn(len(statuses))]
|
*j = statuses[c.Rand.Intn(len(statuses))]
|
||||||
|
@ -88,7 +88,6 @@ func ConvertDownwardAPIFieldLabel(version, label, value string) (string, string,
|
|||||||
"spec.schedulerName",
|
"spec.schedulerName",
|
||||||
"status.phase",
|
"status.phase",
|
||||||
"status.hostIP",
|
"status.hostIP",
|
||||||
"status.hostIPs",
|
|
||||||
"status.podIP",
|
"status.podIP",
|
||||||
"status.podIPs":
|
"status.podIPs":
|
||||||
return label, value, nil
|
return label, value, nil
|
||||||
|
@ -3212,14 +3212,10 @@ type PodDNSConfigOption struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PodIP represents the IP address of a pod.
|
// PodIP represents the IP address of a pod.
|
||||||
|
// IP address information. Each entry includes:
|
||||||
|
// IP: An IP address allocated to the pod. Routable at least within
|
||||||
|
// the cluster.
|
||||||
type PodIP struct {
|
type PodIP struct {
|
||||||
// ip is an IP address assigned to the pod
|
|
||||||
IP string
|
|
||||||
}
|
|
||||||
|
|
||||||
// HostIP represents the IP address of a host.
|
|
||||||
type HostIP struct {
|
|
||||||
// ip is an IP address assigned to the host
|
|
||||||
IP string
|
IP string
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3360,22 +3356,9 @@ type PodStatus struct {
|
|||||||
// give the resources on this node to a higher priority pod that is created after preemption.
|
// give the resources on this node to a higher priority pod that is created after preemption.
|
||||||
// +optional
|
// +optional
|
||||||
NominatedNodeName string
|
NominatedNodeName string
|
||||||
|
|
||||||
// HostIP holds the IP address of the host to which the pod is assigned.
|
|
||||||
// Empty if the pod has not started yet.
|
|
||||||
// A pod can be assigned to a node that has a problem in kubelet which in turns mean that HostIP will
|
|
||||||
// not be updated even if there is node is assigned to pod
|
|
||||||
// +optional
|
// +optional
|
||||||
HostIP string
|
HostIP string
|
||||||
|
|
||||||
// HostIPs holds the IP addresses allocated to the host. If this field is specified, the first entry must
|
|
||||||
// match the hostIP field. This list is empty if the pod has not started yet.
|
|
||||||
// A pod can be assigned to a node that has a problem in kubelet which in turns means that HostIPs will
|
|
||||||
// not be updated even if there is a node is assigned to this pod.
|
|
||||||
// match the hostIP field. This list is empty if no IPs have been allocated yet.
|
|
||||||
// +optional
|
|
||||||
HostIPs []HostIP
|
|
||||||
|
|
||||||
// PodIPs holds all of the known IP addresses allocated to the pod. Pods may be assigned AT MOST
|
// PodIPs holds all of the known IP addresses allocated to the pod. Pods may be assigned AT MOST
|
||||||
// one value for each of IPv4 and IPv6.
|
// one value for each of IPv4 and IPv6.
|
||||||
// +optional
|
// +optional
|
||||||
|
@ -270,17 +270,6 @@ func Convert_v1_PodStatus_To_core_PodStatus(in *v1.PodStatus, out *core.PodStatu
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If both fields (v1.HostIPs and v1.HostIP) are provided and differ, then HostIP is authoritative for compatibility with older kubelets
|
|
||||||
if (len(in.HostIP) > 0 && len(in.HostIPs) > 0) && (in.HostIP != in.HostIPs[0].IP) {
|
|
||||||
out.HostIPs = []core.HostIP{{IP: in.HostIP}}
|
|
||||||
}
|
|
||||||
// at the this point, autoConvert copied v1.HostIPs -> core.HostIPs
|
|
||||||
// if v1.HostIPs was empty but v1.HostIP is not, then set core.HostIPs[0] with v1.HostIP
|
|
||||||
if len(in.HostIP) > 0 && len(in.HostIPs) == 0 {
|
|
||||||
out.HostIPs = []core.HostIP{{IP: in.HostIP}}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -294,11 +283,6 @@ func Convert_core_PodStatus_To_v1_PodStatus(in *core.PodStatus, out *v1.PodStatu
|
|||||||
if len(in.PodIPs) > 0 {
|
if len(in.PodIPs) > 0 {
|
||||||
out.PodIP = in.PodIPs[0].IP
|
out.PodIP = in.PodIPs[0].IP
|
||||||
}
|
}
|
||||||
|
|
||||||
// at the this point autoConvert copied core.HostIPs -> v1.HostIPs
|
|
||||||
if len(in.HostIPs) > 0 {
|
|
||||||
out.HostIP = in.HostIPs[0].IP
|
|
||||||
}
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
32
pkg/apis/core/v1/zz_generated.conversion.go
generated
32
pkg/apis/core/v1/zz_generated.conversion.go
generated
@ -712,16 +712,6 @@ func RegisterConversions(s *runtime.Scheme) error {
|
|||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := s.AddGeneratedConversionFunc((*v1.HostIP)(nil), (*core.HostIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_v1_HostIP_To_core_HostIP(a.(*v1.HostIP), b.(*core.HostIP), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*core.HostIP)(nil), (*v1.HostIP)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
|
||||||
return Convert_core_HostIP_To_v1_HostIP(a.(*core.HostIP), b.(*v1.HostIP), scope)
|
|
||||||
}); err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
if err := s.AddGeneratedConversionFunc((*v1.HostPathVolumeSource)(nil), (*core.HostPathVolumeSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
if err := s.AddGeneratedConversionFunc((*v1.HostPathVolumeSource)(nil), (*core.HostPathVolumeSource)(nil), func(a, b interface{}, scope conversion.Scope) error {
|
||||||
return Convert_v1_HostPathVolumeSource_To_core_HostPathVolumeSource(a.(*v1.HostPathVolumeSource), b.(*core.HostPathVolumeSource), scope)
|
return Convert_v1_HostPathVolumeSource_To_core_HostPathVolumeSource(a.(*v1.HostPathVolumeSource), b.(*core.HostPathVolumeSource), scope)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
@ -4015,26 +4005,6 @@ func Convert_core_HostAlias_To_v1_HostAlias(in *core.HostAlias, out *v1.HostAlia
|
|||||||
return autoConvert_core_HostAlias_To_v1_HostAlias(in, out, s)
|
return autoConvert_core_HostAlias_To_v1_HostAlias(in, out, s)
|
||||||
}
|
}
|
||||||
|
|
||||||
func autoConvert_v1_HostIP_To_core_HostIP(in *v1.HostIP, out *core.HostIP, s conversion.Scope) error {
|
|
||||||
out.IP = in.IP
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert_v1_HostIP_To_core_HostIP is an autogenerated conversion function.
|
|
||||||
func Convert_v1_HostIP_To_core_HostIP(in *v1.HostIP, out *core.HostIP, s conversion.Scope) error {
|
|
||||||
return autoConvert_v1_HostIP_To_core_HostIP(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_core_HostIP_To_v1_HostIP(in *core.HostIP, out *v1.HostIP, s conversion.Scope) error {
|
|
||||||
out.IP = in.IP
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// Convert_core_HostIP_To_v1_HostIP is an autogenerated conversion function.
|
|
||||||
func Convert_core_HostIP_To_v1_HostIP(in *core.HostIP, out *v1.HostIP, s conversion.Scope) error {
|
|
||||||
return autoConvert_core_HostIP_To_v1_HostIP(in, out, s)
|
|
||||||
}
|
|
||||||
|
|
||||||
func autoConvert_v1_HostPathVolumeSource_To_core_HostPathVolumeSource(in *v1.HostPathVolumeSource, out *core.HostPathVolumeSource, s conversion.Scope) error {
|
func autoConvert_v1_HostPathVolumeSource_To_core_HostPathVolumeSource(in *v1.HostPathVolumeSource, out *core.HostPathVolumeSource, s conversion.Scope) error {
|
||||||
out.Path = in.Path
|
out.Path = in.Path
|
||||||
out.Type = (*core.HostPathType)(unsafe.Pointer(in.Type))
|
out.Type = (*core.HostPathType)(unsafe.Pointer(in.Type))
|
||||||
@ -6277,7 +6247,6 @@ func autoConvert_v1_PodStatus_To_core_PodStatus(in *v1.PodStatus, out *core.PodS
|
|||||||
out.Reason = in.Reason
|
out.Reason = in.Reason
|
||||||
out.NominatedNodeName = in.NominatedNodeName
|
out.NominatedNodeName = in.NominatedNodeName
|
||||||
out.HostIP = in.HostIP
|
out.HostIP = in.HostIP
|
||||||
out.HostIPs = *(*[]core.HostIP)(unsafe.Pointer(&in.HostIPs))
|
|
||||||
// WARNING: in.PodIP requires manual conversion: does not exist in peer-type
|
// WARNING: in.PodIP requires manual conversion: does not exist in peer-type
|
||||||
out.PodIPs = *(*[]core.PodIP)(unsafe.Pointer(&in.PodIPs))
|
out.PodIPs = *(*[]core.PodIP)(unsafe.Pointer(&in.PodIPs))
|
||||||
out.StartTime = (*metav1.Time)(unsafe.Pointer(in.StartTime))
|
out.StartTime = (*metav1.Time)(unsafe.Pointer(in.StartTime))
|
||||||
@ -6295,7 +6264,6 @@ func autoConvert_core_PodStatus_To_v1_PodStatus(in *core.PodStatus, out *v1.PodS
|
|||||||
out.Reason = in.Reason
|
out.Reason = in.Reason
|
||||||
out.NominatedNodeName = in.NominatedNodeName
|
out.NominatedNodeName = in.NominatedNodeName
|
||||||
out.HostIP = in.HostIP
|
out.HostIP = in.HostIP
|
||||||
out.HostIPs = *(*[]v1.HostIP)(unsafe.Pointer(&in.HostIPs))
|
|
||||||
out.PodIPs = *(*[]v1.PodIP)(unsafe.Pointer(&in.PodIPs))
|
out.PodIPs = *(*[]v1.PodIP)(unsafe.Pointer(&in.PodIPs))
|
||||||
out.StartTime = (*metav1.Time)(unsafe.Pointer(in.StartTime))
|
out.StartTime = (*metav1.Time)(unsafe.Pointer(in.StartTime))
|
||||||
out.QOSClass = v1.PodQOSClass(in.QOSClass)
|
out.QOSClass = v1.PodQOSClass(in.QOSClass)
|
||||||
|
@ -1044,7 +1044,6 @@ func validateDownwardAPIVolumeFile(file *core.DownwardAPIVolumeFile, fldPath *fi
|
|||||||
if file.ResourceFieldRef != nil {
|
if file.ResourceFieldRef != nil {
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath, "resource", "fieldRef and resourceFieldRef can not be specified simultaneously"))
|
allErrs = append(allErrs, field.Invalid(fldPath, "resource", "fieldRef and resourceFieldRef can not be specified simultaneously"))
|
||||||
}
|
}
|
||||||
allErrs = append(allErrs, validateDownwardAPIHostIPs(file.FieldRef, fldPath.Child("fieldRef"), opts)...)
|
|
||||||
} else if file.ResourceFieldRef != nil {
|
} else if file.ResourceFieldRef != nil {
|
||||||
localValidContainerResourceFieldPathPrefixes := validContainerResourceFieldPathPrefixes
|
localValidContainerResourceFieldPathPrefixes := validContainerResourceFieldPathPrefixes
|
||||||
if opts.AllowDownwardAPIHugePages {
|
if opts.AllowDownwardAPIHugePages {
|
||||||
@ -2330,10 +2329,8 @@ var validEnvDownwardAPIFieldPathExpressions = sets.NewString(
|
|||||||
"spec.nodeName",
|
"spec.nodeName",
|
||||||
"spec.serviceAccountName",
|
"spec.serviceAccountName",
|
||||||
"status.hostIP",
|
"status.hostIP",
|
||||||
"status.hostIPs",
|
|
||||||
"status.podIP",
|
"status.podIP",
|
||||||
"status.podIPs",
|
"status.podIPs")
|
||||||
)
|
|
||||||
|
|
||||||
var validContainerResourceFieldPathExpressions = sets.NewString("limits.cpu", "limits.memory", "limits.ephemeral-storage", "requests.cpu", "requests.memory", "requests.ephemeral-storage")
|
var validContainerResourceFieldPathExpressions = sets.NewString("limits.cpu", "limits.memory", "limits.ephemeral-storage", "requests.cpu", "requests.memory", "requests.ephemeral-storage")
|
||||||
|
|
||||||
@ -2356,7 +2353,6 @@ func validateEnvVarValueFrom(ev core.EnvVar, fldPath *field.Path, opts PodValida
|
|||||||
if ev.ValueFrom.FieldRef != nil {
|
if ev.ValueFrom.FieldRef != nil {
|
||||||
numSources++
|
numSources++
|
||||||
allErrs = append(allErrs, validateObjectFieldSelector(ev.ValueFrom.FieldRef, &validEnvDownwardAPIFieldPathExpressions, fldPath.Child("fieldRef"))...)
|
allErrs = append(allErrs, validateObjectFieldSelector(ev.ValueFrom.FieldRef, &validEnvDownwardAPIFieldPathExpressions, fldPath.Child("fieldRef"))...)
|
||||||
allErrs = append(allErrs, validateDownwardAPIHostIPs(ev.ValueFrom.FieldRef, fldPath.Child("fieldRef"), opts)...)
|
|
||||||
}
|
}
|
||||||
if ev.ValueFrom.ResourceFieldRef != nil {
|
if ev.ValueFrom.ResourceFieldRef != nil {
|
||||||
numSources++
|
numSources++
|
||||||
@ -2427,16 +2423,6 @@ func validateObjectFieldSelector(fs *core.ObjectFieldSelector, expressions *sets
|
|||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateDownwardAPIHostIPs(fieldSel *core.ObjectFieldSelector, fldPath *field.Path, opts PodValidationOptions) field.ErrorList {
|
|
||||||
allErrs := field.ErrorList{}
|
|
||||||
if !opts.AllowHostIPsField {
|
|
||||||
if fieldSel.FieldPath == "status.hostIPs" {
|
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath, "status.hostIPs", "not allowed when feature gate 'PodHostIPs' is not enabled"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return allErrs
|
|
||||||
}
|
|
||||||
|
|
||||||
func validateContainerResourceFieldSelector(fs *core.ResourceFieldSelector, expressions *sets.String, prefixes *sets.String, fldPath *field.Path, volume bool) field.ErrorList {
|
func validateContainerResourceFieldSelector(fs *core.ResourceFieldSelector, expressions *sets.String, prefixes *sets.String, fldPath *field.Path, volume bool) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
|
|
||||||
@ -3429,8 +3415,6 @@ type PodValidationOptions struct {
|
|||||||
AllowExpandedDNSConfig bool
|
AllowExpandedDNSConfig bool
|
||||||
// Allow OSField to be set in the pod spec
|
// Allow OSField to be set in the pod spec
|
||||||
AllowOSField bool
|
AllowOSField bool
|
||||||
// Allow pod spec to use status.hostIPs in downward API
|
|
||||||
AllowHostIPsField bool
|
|
||||||
// Allow sysctl name to contain a slash
|
// Allow sysctl name to contain a slash
|
||||||
AllowSysctlRegexContainSlash bool
|
AllowSysctlRegexContainSlash bool
|
||||||
}
|
}
|
||||||
|
@ -5688,7 +5688,7 @@ func TestValidateEnv(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.hostIPs", "status.podIP", "status.podIPs"`,
|
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.labels": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP", "status.podIPs"`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "metadata.annotations without subscript",
|
name: "metadata.annotations without subscript",
|
||||||
@ -5701,7 +5701,7 @@ func TestValidateEnv(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.hostIPs", "status.podIP", "status.podIPs"`,
|
expectedError: `[0].valueFrom.fieldRef.fieldPath: Unsupported value: "metadata.annotations": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP", "status.podIPs"`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: "metadata.annotations with invalid key",
|
name: "metadata.annotations with invalid key",
|
||||||
@ -5740,7 +5740,7 @@ func TestValidateEnv(t *testing.T) {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
}},
|
}},
|
||||||
expectedError: `valueFrom.fieldRef.fieldPath: Unsupported value: "status.phase": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.hostIPs", "status.podIP", "status.podIPs"`,
|
expectedError: `valueFrom.fieldRef.fieldPath: Unsupported value: "status.phase": supported values: "metadata.name", "metadata.namespace", "metadata.uid", "spec.nodeName", "spec.serviceAccountName", "status.hostIP", "status.podIP", "status.podIPs"`,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, tc := range errorCases {
|
for _, tc := range errorCases {
|
||||||
@ -20455,50 +20455,3 @@ func TestValidateAppArmorProfileFormat(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateDownwardAPIHostIPs(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
expectError bool
|
|
||||||
featureEnabled bool
|
|
||||||
fieldSel *core.ObjectFieldSelector
|
|
||||||
}{
|
|
||||||
{
|
|
||||||
name: "has no hostIPs field, featuregate enabled",
|
|
||||||
expectError: false,
|
|
||||||
featureEnabled: true,
|
|
||||||
fieldSel: &core.ObjectFieldSelector{FieldPath: "status.hostIP"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "has hostIPs field, featuregate enabled",
|
|
||||||
expectError: false,
|
|
||||||
featureEnabled: true,
|
|
||||||
fieldSel: &core.ObjectFieldSelector{FieldPath: "status.hostIPs"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "has no hostIPs field, featuregate disabled",
|
|
||||||
expectError: false,
|
|
||||||
featureEnabled: false,
|
|
||||||
fieldSel: &core.ObjectFieldSelector{FieldPath: "status.hostIP"},
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: "has hostIPs field, featuregate disabled",
|
|
||||||
expectError: true,
|
|
||||||
featureEnabled: false,
|
|
||||||
fieldSel: &core.ObjectFieldSelector{FieldPath: "status.hostIPs"},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
for _, testCase := range testCases {
|
|
||||||
t.Run(testCase.name, func(t *testing.T) {
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodHostIPs, testCase.featureEnabled)()
|
|
||||||
|
|
||||||
errs := validateDownwardAPIHostIPs(testCase.fieldSel, field.NewPath("fieldSel"), PodValidationOptions{AllowHostIPsField: testCase.featureEnabled})
|
|
||||||
if testCase.expectError && len(errs) == 0 {
|
|
||||||
t.Errorf("Unexpected success")
|
|
||||||
}
|
|
||||||
if !testCase.expectError && len(errs) != 0 {
|
|
||||||
t.Errorf("Unexpected error(s): %v", errs)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
21
pkg/apis/core/zz_generated.deepcopy.go
generated
21
pkg/apis/core/zz_generated.deepcopy.go
generated
@ -1802,22 +1802,6 @@ func (in *HostAlias) DeepCopy() *HostAlias {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *HostIP) DeepCopyInto(out *HostIP) {
|
|
||||||
*out = *in
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostIP.
|
|
||||||
func (in *HostIP) DeepCopy() *HostIP {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(HostIP)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *HostPathVolumeSource) DeepCopyInto(out *HostPathVolumeSource) {
|
func (in *HostPathVolumeSource) DeepCopyInto(out *HostPathVolumeSource) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -3990,11 +3974,6 @@ func (in *PodStatus) DeepCopyInto(out *PodStatus) {
|
|||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.HostIPs != nil {
|
|
||||||
in, out := &in.HostIPs, &out.HostIPs
|
|
||||||
*out = make([]HostIP, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
if in.PodIPs != nil {
|
if in.PodIPs != nil {
|
||||||
in, out := &in.PodIPs, &out.PodIPs
|
in, out := &in.PodIPs, &out.PodIPs
|
||||||
*out = make([]PodIP, len(*in))
|
*out = make([]PodIP, len(*in))
|
||||||
|
@ -412,13 +412,6 @@ const (
|
|||||||
// Enables ipv6 dual stack
|
// Enables ipv6 dual stack
|
||||||
IPv6DualStack featuregate.Feature = "IPv6DualStack"
|
IPv6DualStack featuregate.Feature = "IPv6DualStack"
|
||||||
|
|
||||||
// owner: @wzshiming
|
|
||||||
// kep: http://kep.k8s.io/2681
|
|
||||||
// alpha: v1.24
|
|
||||||
//
|
|
||||||
// Adds pod.status.hostIPs and downward API
|
|
||||||
PodHostIPs featuregate.Feature = "PodHostIPs"
|
|
||||||
|
|
||||||
// owner: @robscott @freehan
|
// owner: @robscott @freehan
|
||||||
// kep: http://kep.k8s.io/752
|
// kep: http://kep.k8s.io/752
|
||||||
// alpha: v1.16
|
// alpha: v1.16
|
||||||
@ -943,7 +936,6 @@ var defaultKubernetesFeatureGates = map[featuregate.Feature]featuregate.FeatureS
|
|||||||
NonPreemptingPriority: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
NonPreemptingPriority: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
||||||
PodOverhead: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
|
PodOverhead: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
|
||||||
IPv6DualStack: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
IPv6DualStack: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
||||||
PodHostIPs: {Default: false, PreRelease: featuregate.Alpha},
|
|
||||||
EndpointSlice: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
EndpointSlice: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
||||||
EndpointSliceProxying: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
EndpointSliceProxying: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
|
||||||
EndpointSliceTerminatingCondition: {Default: true, PreRelease: featuregate.Beta},
|
EndpointSliceTerminatingCondition: {Default: true, PreRelease: featuregate.Beta},
|
||||||
|
52
pkg/generated/openapi/zz_generated.openapi.go
generated
52
pkg/generated/openapi/zz_generated.openapi.go
generated
@ -369,7 +369,6 @@ func GetOpenAPIDefinitions(ref common.ReferenceCallback) map[string]common.OpenA
|
|||||||
"k8s.io/api/core/v1.HTTPGetAction": schema_k8sio_api_core_v1_HTTPGetAction(ref),
|
"k8s.io/api/core/v1.HTTPGetAction": schema_k8sio_api_core_v1_HTTPGetAction(ref),
|
||||||
"k8s.io/api/core/v1.HTTPHeader": schema_k8sio_api_core_v1_HTTPHeader(ref),
|
"k8s.io/api/core/v1.HTTPHeader": schema_k8sio_api_core_v1_HTTPHeader(ref),
|
||||||
"k8s.io/api/core/v1.HostAlias": schema_k8sio_api_core_v1_HostAlias(ref),
|
"k8s.io/api/core/v1.HostAlias": schema_k8sio_api_core_v1_HostAlias(ref),
|
||||||
"k8s.io/api/core/v1.HostIP": schema_k8sio_api_core_v1_HostIP(ref),
|
|
||||||
"k8s.io/api/core/v1.HostPathVolumeSource": schema_k8sio_api_core_v1_HostPathVolumeSource(ref),
|
"k8s.io/api/core/v1.HostPathVolumeSource": schema_k8sio_api_core_v1_HostPathVolumeSource(ref),
|
||||||
"k8s.io/api/core/v1.ISCSIPersistentVolumeSource": schema_k8sio_api_core_v1_ISCSIPersistentVolumeSource(ref),
|
"k8s.io/api/core/v1.ISCSIPersistentVolumeSource": schema_k8sio_api_core_v1_ISCSIPersistentVolumeSource(ref),
|
||||||
"k8s.io/api/core/v1.ISCSIVolumeSource": schema_k8sio_api_core_v1_ISCSIVolumeSource(ref),
|
"k8s.io/api/core/v1.ISCSIVolumeSource": schema_k8sio_api_core_v1_ISCSIVolumeSource(ref),
|
||||||
@ -18066,26 +18065,6 @@ func schema_k8sio_api_core_v1_HostAlias(ref common.ReferenceCallback) common.Ope
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func schema_k8sio_api_core_v1_HostIP(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
|
||||||
return common.OpenAPIDefinition{
|
|
||||||
Schema: spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "HostIP address information for entries in the (plural) HostIPs field.",
|
|
||||||
Type: []string{"object"},
|
|
||||||
Properties: map[string]spec.Schema{
|
|
||||||
"ip": {
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "IP is the IP address assigned to the host",
|
|
||||||
Type: []string{"string"},
|
|
||||||
Format: "",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func schema_k8sio_api_core_v1_HostPathVolumeSource(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
func schema_k8sio_api_core_v1_HostPathVolumeSource(ref common.ReferenceCallback) common.OpenAPIDefinition {
|
||||||
return common.OpenAPIDefinition{
|
return common.OpenAPIDefinition{
|
||||||
Schema: spec.Schema{
|
Schema: spec.Schema{
|
||||||
@ -21416,12 +21395,12 @@ func schema_k8sio_api_core_v1_PodIP(ref common.ReferenceCallback) common.OpenAPI
|
|||||||
return common.OpenAPIDefinition{
|
return common.OpenAPIDefinition{
|
||||||
Schema: spec.Schema{
|
Schema: spec.Schema{
|
||||||
SchemaProps: spec.SchemaProps{
|
SchemaProps: spec.SchemaProps{
|
||||||
Description: "PodIP address information for entries in the (plural) PodIPs field.",
|
Description: "IP address information for entries in the (plural) PodIPs field. Each entry includes:\n IP: An IP address allocated to the pod. Routable at least within the cluster.",
|
||||||
Type: []string{"object"},
|
Type: []string{"object"},
|
||||||
Properties: map[string]spec.Schema{
|
Properties: map[string]spec.Schema{
|
||||||
"ip": {
|
"ip": {
|
||||||
SchemaProps: spec.SchemaProps{
|
SchemaProps: spec.SchemaProps{
|
||||||
Description: "IP is the IP address assigned to the pod",
|
Description: "ip is an IP address (IPv4 or IPv6) assigned to the pod",
|
||||||
Type: []string{"string"},
|
Type: []string{"string"},
|
||||||
Format: "",
|
Format: "",
|
||||||
},
|
},
|
||||||
@ -22265,35 +22244,14 @@ func schema_k8sio_api_core_v1_PodStatus(ref common.ReferenceCallback) common.Ope
|
|||||||
},
|
},
|
||||||
"hostIP": {
|
"hostIP": {
|
||||||
SchemaProps: spec.SchemaProps{
|
SchemaProps: spec.SchemaProps{
|
||||||
Description: "hostIP holds the IP address of the host to which the pod is assigned. Empty if the pod has not started yet. A pod can be assigned to a node that has a problem in kubelet which in turns mean that HostIP will not be updated even if there is node is assigned to pod",
|
Description: "IP address of the host to which the pod is assigned. Empty if not yet scheduled.",
|
||||||
Type: []string{"string"},
|
Type: []string{"string"},
|
||||||
Format: "",
|
Format: "",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
"hostIPs": {
|
|
||||||
VendorExtensible: spec.VendorExtensible{
|
|
||||||
Extensions: spec.Extensions{
|
|
||||||
"x-kubernetes-list-type": "set",
|
|
||||||
"x-kubernetes-patch-merge-key": "ip",
|
|
||||||
"x-kubernetes-patch-strategy": "merge",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Description: "hostIPs holds the IP addresses allocated to the host. If this field is specified, the first entry must match the hostIP field. This list is empty if the pod has not started yet. A pod can be assigned to a node that has a problem in kubelet which in turns means that HostIPs will not be updated even if there is a node is assigned to this pod.",
|
|
||||||
Type: []string{"array"},
|
|
||||||
Items: &spec.SchemaOrArray{
|
|
||||||
Schema: &spec.Schema{
|
|
||||||
SchemaProps: spec.SchemaProps{
|
|
||||||
Default: map[string]interface{}{},
|
|
||||||
Ref: ref("k8s.io/api/core/v1.HostIP"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
"podIP": {
|
"podIP": {
|
||||||
SchemaProps: spec.SchemaProps{
|
SchemaProps: spec.SchemaProps{
|
||||||
Description: "podIP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.",
|
Description: "IP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.",
|
||||||
Type: []string{"string"},
|
Type: []string{"string"},
|
||||||
Format: "",
|
Format: "",
|
||||||
},
|
},
|
||||||
@ -22377,7 +22335,7 @@ func schema_k8sio_api_core_v1_PodStatus(ref common.ReferenceCallback) common.Ope
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
Dependencies: []string{
|
Dependencies: []string{
|
||||||
"k8s.io/api/core/v1.ContainerStatus", "k8s.io/api/core/v1.HostIP", "k8s.io/api/core/v1.PodCondition", "k8s.io/api/core/v1.PodIP", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
|
"k8s.io/api/core/v1.ContainerStatus", "k8s.io/api/core/v1.PodCondition", "k8s.io/api/core/v1.PodIP", "k8s.io/apimachinery/pkg/apis/meta/v1.Time"},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -826,19 +826,6 @@ func (kl *Kubelet) podFieldSelectorRuntimeValue(fs *v1.ObjectFieldSelector, pod
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
return hostIPs[0].String(), nil
|
return hostIPs[0].String(), nil
|
||||||
case "status.hostIPs":
|
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.PodHostIPs) {
|
|
||||||
return "", nil
|
|
||||||
}
|
|
||||||
hostIPs, err := kl.getHostIPsAnyWay()
|
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
ips := make([]string, 0, len(hostIPs))
|
|
||||||
for _, ip := range hostIPs {
|
|
||||||
ips = append(ips, ip.String())
|
|
||||||
}
|
|
||||||
return strings.Join(ips, ","), nil
|
|
||||||
case "status.podIP":
|
case "status.podIP":
|
||||||
return podIP, nil
|
return podIP, nil
|
||||||
case "status.podIPs":
|
case "status.podIPs":
|
||||||
@ -1530,13 +1517,6 @@ func (kl *Kubelet) generateAPIPodStatus(pod *v1.Pod, podStatus *kubecontainer.Po
|
|||||||
klog.V(4).InfoS("Cannot get host IPs", "err", err)
|
klog.V(4).InfoS("Cannot get host IPs", "err", err)
|
||||||
} else {
|
} else {
|
||||||
s.HostIP = hostIPs[0].String()
|
s.HostIP = hostIPs[0].String()
|
||||||
if utilfeature.DefaultFeatureGate.Enabled(features.PodHostIPs) {
|
|
||||||
ips := make([]v1.HostIP, 0, len(hostIPs))
|
|
||||||
for _, hostIP := range hostIPs {
|
|
||||||
ips = append(ips, v1.HostIP{IP: hostIP.String()})
|
|
||||||
}
|
|
||||||
s.HostIPs = ips
|
|
||||||
}
|
|
||||||
// HostNetwork Pods inherit the node IPs as PodIPs. They are immutable once set,
|
// HostNetwork Pods inherit the node IPs as PodIPs. They are immutable once set,
|
||||||
// other than that if the node becomes dual-stack, we add the secondary IP.
|
// other than that if the node becomes dual-stack, we add the secondary IP.
|
||||||
if kubecontainer.IsHostNetworkPod(pod) {
|
if kubecontainer.IsHostNetworkPod(pod) {
|
||||||
|
@ -38,10 +38,8 @@ import (
|
|||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/diff"
|
"k8s.io/apimachinery/pkg/util/diff"
|
||||||
utilfeature "k8s.io/apiserver/pkg/util/feature"
|
|
||||||
core "k8s.io/client-go/testing"
|
core "k8s.io/client-go/testing"
|
||||||
"k8s.io/client-go/tools/record"
|
"k8s.io/client-go/tools/record"
|
||||||
featuregatetesting "k8s.io/component-base/featuregate/testing"
|
|
||||||
netutils "k8s.io/utils/net"
|
netutils "k8s.io/utils/net"
|
||||||
|
|
||||||
// TODO: remove this import if
|
// TODO: remove this import if
|
||||||
@ -49,7 +47,6 @@ import (
|
|||||||
// to "v1"?
|
// to "v1"?
|
||||||
|
|
||||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
|
||||||
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
|
||||||
"k8s.io/kubernetes/pkg/kubelet/cri/streaming/portforward"
|
"k8s.io/kubernetes/pkg/kubelet/cri/streaming/portforward"
|
||||||
@ -2473,10 +2470,6 @@ func TestConvertToAPIContainerStatuses(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func Test_generateAPIPodStatus(t *testing.T) {
|
func Test_generateAPIPodStatus(t *testing.T) {
|
||||||
if !utilfeature.DefaultFeatureGate.Enabled(features.PodHostIPs) {
|
|
||||||
defer featuregatetesting.SetFeatureGateDuringTest(t, utilfeature.DefaultFeatureGate, features.PodHostIPs, true)()
|
|
||||||
}
|
|
||||||
|
|
||||||
desiredState := v1.PodSpec{
|
desiredState := v1.PodSpec{
|
||||||
NodeName: "machine",
|
NodeName: "machine",
|
||||||
Containers: []v1.Container{
|
Containers: []v1.Container{
|
||||||
@ -2517,7 +2510,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
|
|||||||
expected: v1.PodStatus{
|
expected: v1.PodStatus{
|
||||||
Phase: v1.PodRunning,
|
Phase: v1.PodRunning,
|
||||||
HostIP: "127.0.0.1",
|
HostIP: "127.0.0.1",
|
||||||
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
|
|
||||||
QOSClass: v1.PodQOSBestEffort,
|
QOSClass: v1.PodQOSBestEffort,
|
||||||
Conditions: []v1.PodCondition{
|
Conditions: []v1.PodCondition{
|
||||||
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
|
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
|
||||||
@ -2552,7 +2544,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
|
|||||||
expected: v1.PodStatus{
|
expected: v1.PodStatus{
|
||||||
Phase: v1.PodRunning,
|
Phase: v1.PodRunning,
|
||||||
HostIP: "127.0.0.1",
|
HostIP: "127.0.0.1",
|
||||||
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
|
|
||||||
QOSClass: v1.PodQOSBestEffort,
|
QOSClass: v1.PodQOSBestEffort,
|
||||||
Conditions: []v1.PodCondition{
|
Conditions: []v1.PodCondition{
|
||||||
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
|
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
|
||||||
@ -2588,7 +2579,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
|
|||||||
expected: v1.PodStatus{
|
expected: v1.PodStatus{
|
||||||
Phase: v1.PodSucceeded,
|
Phase: v1.PodSucceeded,
|
||||||
HostIP: "127.0.0.1",
|
HostIP: "127.0.0.1",
|
||||||
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
|
|
||||||
QOSClass: v1.PodQOSBestEffort,
|
QOSClass: v1.PodQOSBestEffort,
|
||||||
Conditions: []v1.PodCondition{
|
Conditions: []v1.PodCondition{
|
||||||
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
|
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
|
||||||
@ -2628,7 +2618,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
|
|||||||
expected: v1.PodStatus{
|
expected: v1.PodStatus{
|
||||||
Phase: v1.PodSucceeded,
|
Phase: v1.PodSucceeded,
|
||||||
HostIP: "127.0.0.1",
|
HostIP: "127.0.0.1",
|
||||||
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
|
|
||||||
QOSClass: v1.PodQOSBestEffort,
|
QOSClass: v1.PodQOSBestEffort,
|
||||||
Conditions: []v1.PodCondition{
|
Conditions: []v1.PodCondition{
|
||||||
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
|
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
|
||||||
@ -2677,7 +2666,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
|
|||||||
expected: v1.PodStatus{
|
expected: v1.PodStatus{
|
||||||
Phase: v1.PodSucceeded,
|
Phase: v1.PodSucceeded,
|
||||||
HostIP: "127.0.0.1",
|
HostIP: "127.0.0.1",
|
||||||
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
|
|
||||||
QOSClass: v1.PodQOSBestEffort,
|
QOSClass: v1.PodQOSBestEffort,
|
||||||
Conditions: []v1.PodCondition{
|
Conditions: []v1.PodCondition{
|
||||||
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
|
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
|
||||||
@ -2715,7 +2703,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
|
|||||||
expected: v1.PodStatus{
|
expected: v1.PodStatus{
|
||||||
Phase: v1.PodPending,
|
Phase: v1.PodPending,
|
||||||
HostIP: "127.0.0.1",
|
HostIP: "127.0.0.1",
|
||||||
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
|
|
||||||
QOSClass: v1.PodQOSBestEffort,
|
QOSClass: v1.PodQOSBestEffort,
|
||||||
Conditions: []v1.PodCondition{
|
Conditions: []v1.PodCondition{
|
||||||
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
|
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
|
||||||
@ -2765,7 +2752,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
|
|||||||
Reason: "Test",
|
Reason: "Test",
|
||||||
Message: "test",
|
Message: "test",
|
||||||
HostIP: "127.0.0.1",
|
HostIP: "127.0.0.1",
|
||||||
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
|
|
||||||
QOSClass: v1.PodQOSBestEffort,
|
QOSClass: v1.PodQOSBestEffort,
|
||||||
Conditions: []v1.PodCondition{
|
Conditions: []v1.PodCondition{
|
||||||
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
|
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
|
||||||
@ -2819,7 +2805,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
|
|||||||
expected: v1.PodStatus{
|
expected: v1.PodStatus{
|
||||||
Phase: v1.PodRunning,
|
Phase: v1.PodRunning,
|
||||||
HostIP: "127.0.0.1",
|
HostIP: "127.0.0.1",
|
||||||
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
|
|
||||||
QOSClass: v1.PodQOSBestEffort,
|
QOSClass: v1.PodQOSBestEffort,
|
||||||
Conditions: []v1.PodCondition{
|
Conditions: []v1.PodCondition{
|
||||||
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
|
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
|
||||||
|
2293
staging/src/k8s.io/api/core/v1/generated.pb.go
generated
2293
staging/src/k8s.io/api/core/v1/generated.pb.go
generated
File diff suppressed because it is too large
Load Diff
@ -1767,12 +1767,6 @@ message HostAlias {
|
|||||||
repeated string hostnames = 2;
|
repeated string hostnames = 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// HostIP address information for entries in the (plural) HostIPs field.
|
|
||||||
message HostIP {
|
|
||||||
// IP is the IP address assigned to the host
|
|
||||||
optional string ip = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Represents a host path mapped into a pod.
|
// Represents a host path mapped into a pod.
|
||||||
// Host path volumes do not support ownership management or SELinux relabeling.
|
// Host path volumes do not support ownership management or SELinux relabeling.
|
||||||
message HostPathVolumeSource {
|
message HostPathVolumeSource {
|
||||||
@ -3236,9 +3230,11 @@ message PodExecOptions {
|
|||||||
repeated string command = 6;
|
repeated string command = 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodIP address information for entries in the (plural) PodIPs field.
|
// IP address information for entries in the (plural) PodIPs field.
|
||||||
|
// Each entry includes:
|
||||||
|
// IP: An IP address allocated to the pod. Routable at least within the cluster.
|
||||||
message PodIP {
|
message PodIP {
|
||||||
// IP is the IP address assigned to the pod
|
// ip is an IP address (IPv4 or IPv6) assigned to the pod
|
||||||
optional string ip = 1;
|
optional string ip = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3778,24 +3774,11 @@ message PodStatus {
|
|||||||
// +optional
|
// +optional
|
||||||
optional string nominatedNodeName = 11;
|
optional string nominatedNodeName = 11;
|
||||||
|
|
||||||
// hostIP holds the IP address of the host to which the pod is assigned.
|
// IP address of the host to which the pod is assigned. Empty if not yet scheduled.
|
||||||
// Empty if the pod has not started yet.
|
|
||||||
// A pod can be assigned to a node that has a problem in kubelet which in turns mean that HostIP will
|
|
||||||
// not be updated even if there is node is assigned to pod
|
|
||||||
// +optional
|
// +optional
|
||||||
optional string hostIP = 5;
|
optional string hostIP = 5;
|
||||||
|
|
||||||
// hostIPs holds the IP addresses allocated to the host. If this field is specified, the first entry must
|
// IP address allocated to the pod. Routable at least within the cluster.
|
||||||
// match the hostIP field. This list is empty if the pod has not started yet.
|
|
||||||
// A pod can be assigned to a node that has a problem in kubelet which in turns means that HostIPs will
|
|
||||||
// not be updated even if there is a node is assigned to this pod.
|
|
||||||
// +optional
|
|
||||||
// +patchStrategy=merge
|
|
||||||
// +patchMergeKey=ip
|
|
||||||
// +listType=set
|
|
||||||
repeated HostIP hostIPs = 14;
|
|
||||||
|
|
||||||
// podIP address allocated to the pod. Routable at least within the cluster.
|
|
||||||
// Empty if not yet allocated.
|
// Empty if not yet allocated.
|
||||||
// +optional
|
// +optional
|
||||||
optional string podIP = 6;
|
optional string podIP = 6;
|
||||||
|
@ -3605,15 +3605,11 @@ type PodDNSConfigOption struct {
|
|||||||
Value *string `json:"value,omitempty" protobuf:"bytes,2,opt,name=value"`
|
Value *string `json:"value,omitempty" protobuf:"bytes,2,opt,name=value"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// PodIP address information for entries in the (plural) PodIPs field.
|
// IP address information for entries in the (plural) PodIPs field.
|
||||||
|
// Each entry includes:
|
||||||
|
// IP: An IP address allocated to the pod. Routable at least within the cluster.
|
||||||
type PodIP struct {
|
type PodIP struct {
|
||||||
// IP is the IP address assigned to the pod
|
// ip is an IP address (IPv4 or IPv6) assigned to the pod
|
||||||
IP string `json:"ip,omitempty" protobuf:"bytes,1,opt,name=ip"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// HostIP address information for entries in the (plural) HostIPs field.
|
|
||||||
type HostIP struct {
|
|
||||||
// IP is the IP address assigned to the host
|
|
||||||
IP string `json:"ip,omitempty" protobuf:"bytes,1,opt,name=ip"`
|
IP string `json:"ip,omitempty" protobuf:"bytes,1,opt,name=ip"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3834,24 +3830,10 @@ type PodStatus struct {
|
|||||||
// +optional
|
// +optional
|
||||||
NominatedNodeName string `json:"nominatedNodeName,omitempty" protobuf:"bytes,11,opt,name=nominatedNodeName"`
|
NominatedNodeName string `json:"nominatedNodeName,omitempty" protobuf:"bytes,11,opt,name=nominatedNodeName"`
|
||||||
|
|
||||||
// hostIP holds the IP address of the host to which the pod is assigned.
|
// IP address of the host to which the pod is assigned. Empty if not yet scheduled.
|
||||||
// Empty if the pod has not started yet.
|
|
||||||
// A pod can be assigned to a node that has a problem in kubelet which in turns mean that HostIP will
|
|
||||||
// not be updated even if there is node is assigned to pod
|
|
||||||
// +optional
|
// +optional
|
||||||
HostIP string `json:"hostIP,omitempty" protobuf:"bytes,5,opt,name=hostIP"`
|
HostIP string `json:"hostIP,omitempty" protobuf:"bytes,5,opt,name=hostIP"`
|
||||||
|
// IP address allocated to the pod. Routable at least within the cluster.
|
||||||
// hostIPs holds the IP addresses allocated to the host. If this field is specified, the first entry must
|
|
||||||
// match the hostIP field. This list is empty if the pod has not started yet.
|
|
||||||
// A pod can be assigned to a node that has a problem in kubelet which in turns means that HostIPs will
|
|
||||||
// not be updated even if there is a node is assigned to this pod.
|
|
||||||
// +optional
|
|
||||||
// +patchStrategy=merge
|
|
||||||
// +patchMergeKey=ip
|
|
||||||
// +listType=set
|
|
||||||
HostIPs []HostIP `json:"hostIPs,omitempty" protobuf:"bytes,14,rep,name=hostIPs" patchStrategy:"merge" patchMergeKey:"ip"`
|
|
||||||
|
|
||||||
// podIP address allocated to the pod. Routable at least within the cluster.
|
|
||||||
// Empty if not yet allocated.
|
// Empty if not yet allocated.
|
||||||
// +optional
|
// +optional
|
||||||
PodIP string `json:"podIP,omitempty" protobuf:"bytes,6,opt,name=podIP"`
|
PodIP string `json:"podIP,omitempty" protobuf:"bytes,6,opt,name=podIP"`
|
||||||
|
@ -825,15 +825,6 @@ func (HostAlias) SwaggerDoc() map[string]string {
|
|||||||
return map_HostAlias
|
return map_HostAlias
|
||||||
}
|
}
|
||||||
|
|
||||||
var map_HostIP = map[string]string{
|
|
||||||
"": "HostIP address information for entries in the (plural) HostIPs field.",
|
|
||||||
"ip": "IP is the IP address assigned to the host",
|
|
||||||
}
|
|
||||||
|
|
||||||
func (HostIP) SwaggerDoc() map[string]string {
|
|
||||||
return map_HostIP
|
|
||||||
}
|
|
||||||
|
|
||||||
var map_HostPathVolumeSource = map[string]string{
|
var map_HostPathVolumeSource = map[string]string{
|
||||||
"": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.",
|
"": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.",
|
||||||
"path": "path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath",
|
"path": "path of the directory on the host. If the path is a symlink, it will follow the link to the real path. More info: https://kubernetes.io/docs/concepts/storage/volumes#hostpath",
|
||||||
@ -1543,8 +1534,8 @@ func (PodExecOptions) SwaggerDoc() map[string]string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var map_PodIP = map[string]string{
|
var map_PodIP = map[string]string{
|
||||||
"": "PodIP address information for entries in the (plural) PodIPs field.",
|
"": "IP address information for entries in the (plural) PodIPs field. Each entry includes:\n IP: An IP address allocated to the pod. Routable at least within the cluster.",
|
||||||
"ip": "IP is the IP address assigned to the pod",
|
"ip": "ip is an IP address (IPv4 or IPv6) assigned to the pod",
|
||||||
}
|
}
|
||||||
|
|
||||||
func (PodIP) SwaggerDoc() map[string]string {
|
func (PodIP) SwaggerDoc() map[string]string {
|
||||||
@ -1692,9 +1683,8 @@ var map_PodStatus = map[string]string{
|
|||||||
"message": "A human readable message indicating details about why the pod is in this condition.",
|
"message": "A human readable message indicating details about why the pod is in this condition.",
|
||||||
"reason": "A brief CamelCase message indicating details about why the pod is in this state. e.g. 'Evicted'",
|
"reason": "A brief CamelCase message indicating details about why the pod is in this state. e.g. 'Evicted'",
|
||||||
"nominatedNodeName": "nominatedNodeName is set only when this pod preempts other pods on the node, but it cannot be scheduled right away as preemption victims receive their graceful termination periods. This field does not guarantee that the pod will be scheduled on this node. Scheduler may decide to place the pod elsewhere if other nodes become available sooner. Scheduler may also decide to give the resources on this node to a higher priority pod that is created after preemption. As a result, this field may be different than PodSpec.nodeName when the pod is scheduled.",
|
"nominatedNodeName": "nominatedNodeName is set only when this pod preempts other pods on the node, but it cannot be scheduled right away as preemption victims receive their graceful termination periods. This field does not guarantee that the pod will be scheduled on this node. Scheduler may decide to place the pod elsewhere if other nodes become available sooner. Scheduler may also decide to give the resources on this node to a higher priority pod that is created after preemption. As a result, this field may be different than PodSpec.nodeName when the pod is scheduled.",
|
||||||
"hostIP": "hostIP holds the IP address of the host to which the pod is assigned. Empty if the pod has not started yet. A pod can be assigned to a node that has a problem in kubelet which in turns mean that HostIP will not be updated even if there is node is assigned to pod",
|
"hostIP": "IP address of the host to which the pod is assigned. Empty if not yet scheduled.",
|
||||||
"hostIPs": "hostIPs holds the IP addresses allocated to the host. If this field is specified, the first entry must match the hostIP field. This list is empty if the pod has not started yet. A pod can be assigned to a node that has a problem in kubelet which in turns means that HostIPs will not be updated even if there is a node is assigned to this pod.",
|
"podIP": "IP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.",
|
||||||
"podIP": "podIP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.",
|
|
||||||
"podIPs": "podIPs holds the IP addresses allocated to the pod. If this field is specified, the 0th entry must match the podIP field. Pods may be allocated at most 1 value for each of IPv4 and IPv6. This list is empty if no IPs have been allocated yet.",
|
"podIPs": "podIPs holds the IP addresses allocated to the pod. If this field is specified, the 0th entry must match the podIP field. Pods may be allocated at most 1 value for each of IPv4 and IPv6. This list is empty if no IPs have been allocated yet.",
|
||||||
"startTime": "RFC 3339 date and time at which the object was acknowledged by the Kubelet. This is before the Kubelet pulled the container image(s) for the pod.",
|
"startTime": "RFC 3339 date and time at which the object was acknowledged by the Kubelet. This is before the Kubelet pulled the container image(s) for the pod.",
|
||||||
"initContainerStatuses": "The list has one entry per init container in the manifest. The most recent successful init container will have ready = true, the most recently started container will have startTime set. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status",
|
"initContainerStatuses": "The list has one entry per init container in the manifest. The most recent successful init container will have ready = true, the most recently started container will have startTime set. More info: https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle#pod-and-container-status",
|
||||||
|
@ -1802,22 +1802,6 @@ func (in *HostAlias) DeepCopy() *HostAlias {
|
|||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
|
||||||
func (in *HostIP) DeepCopyInto(out *HostIP) {
|
|
||||||
*out = *in
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new HostIP.
|
|
||||||
func (in *HostIP) DeepCopy() *HostIP {
|
|
||||||
if in == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
out := new(HostIP)
|
|
||||||
in.DeepCopyInto(out)
|
|
||||||
return out
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||||
func (in *HostPathVolumeSource) DeepCopyInto(out *HostPathVolumeSource) {
|
func (in *HostPathVolumeSource) DeepCopyInto(out *HostPathVolumeSource) {
|
||||||
*out = *in
|
*out = *in
|
||||||
@ -3988,11 +3972,6 @@ func (in *PodStatus) DeepCopyInto(out *PodStatus) {
|
|||||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if in.HostIPs != nil {
|
|
||||||
in, out := &in.HostIPs, &out.HostIPs
|
|
||||||
*out = make([]HostIP, len(*in))
|
|
||||||
copy(*out, *in)
|
|
||||||
}
|
|
||||||
if in.PodIPs != nil {
|
if in.PodIPs != nil {
|
||||||
in, out := &in.PodIPs, &out.PodIPs
|
in, out := &in.PodIPs, &out.PodIPs
|
||||||
*out = make([]PodIP, len(*in))
|
*out = make([]PodIP, len(*in))
|
||||||
|
@ -1582,11 +1582,6 @@
|
|||||||
"reason": "reasonValue",
|
"reason": "reasonValue",
|
||||||
"nominatedNodeName": "nominatedNodeNameValue",
|
"nominatedNodeName": "nominatedNodeNameValue",
|
||||||
"hostIP": "hostIPValue",
|
"hostIP": "hostIPValue",
|
||||||
"hostIPs": [
|
|
||||||
{
|
|
||||||
"ip": "ipValue"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"podIP": "podIPValue",
|
"podIP": "podIPValue",
|
||||||
"podIPs": [
|
"podIPs": [
|
||||||
{
|
{
|
||||||
|
BIN
staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.pb
vendored
BIN
staging/src/k8s.io/api/testdata/HEAD/core.v1.Pod.pb
vendored
Binary file not shown.
@ -1159,8 +1159,6 @@ status:
|
|||||||
message: messageValue
|
message: messageValue
|
||||||
reason: reasonValue
|
reason: reasonValue
|
||||||
hostIP: hostIPValue
|
hostIP: hostIPValue
|
||||||
hostIPs:
|
|
||||||
- ip: ipValue
|
|
||||||
initContainerStatuses:
|
initContainerStatuses:
|
||||||
- containerID: containerIDValue
|
- containerID: containerIDValue
|
||||||
image: imageValue
|
image: imageValue
|
||||||
|
@ -60,11 +60,6 @@
|
|||||||
"reason": "reasonValue",
|
"reason": "reasonValue",
|
||||||
"nominatedNodeName": "nominatedNodeNameValue",
|
"nominatedNodeName": "nominatedNodeNameValue",
|
||||||
"hostIP": "hostIPValue",
|
"hostIP": "hostIPValue",
|
||||||
"hostIPs": [
|
|
||||||
{
|
|
||||||
"ip": "ipValue"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"podIP": "podIPValue",
|
"podIP": "podIPValue",
|
||||||
"podIPs": [
|
"podIPs": [
|
||||||
{
|
{
|
||||||
|
Binary file not shown.
@ -114,8 +114,6 @@ status:
|
|||||||
message: messageValue
|
message: messageValue
|
||||||
reason: reasonValue
|
reason: reasonValue
|
||||||
hostIP: hostIPValue
|
hostIP: hostIPValue
|
||||||
hostIPs:
|
|
||||||
- ip: ipValue
|
|
||||||
initContainerStatuses:
|
initContainerStatuses:
|
||||||
- containerID: containerIDValue
|
- containerID: containerIDValue
|
||||||
image: imageValue
|
image: imageValue
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
// Code generated by applyconfiguration-gen. DO NOT EDIT.
|
|
||||||
|
|
||||||
package v1
|
|
||||||
|
|
||||||
// HostIPApplyConfiguration represents an declarative configuration of the HostIP type for use
|
|
||||||
// with apply.
|
|
||||||
type HostIPApplyConfiguration struct {
|
|
||||||
IP *string `json:"ip,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// HostIPApplyConfiguration constructs an declarative configuration of the HostIP type for use with
|
|
||||||
// apply.
|
|
||||||
func HostIP() *HostIPApplyConfiguration {
|
|
||||||
return &HostIPApplyConfiguration{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithIP sets the IP field in the declarative configuration to the given value
|
|
||||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
|
||||||
// If called multiple times, the IP field is set to the value of the last call.
|
|
||||||
func (b *HostIPApplyConfiguration) WithIP(value string) *HostIPApplyConfiguration {
|
|
||||||
b.IP = &value
|
|
||||||
return b
|
|
||||||
}
|
|
@ -32,7 +32,6 @@ type PodStatusApplyConfiguration struct {
|
|||||||
Reason *string `json:"reason,omitempty"`
|
Reason *string `json:"reason,omitempty"`
|
||||||
NominatedNodeName *string `json:"nominatedNodeName,omitempty"`
|
NominatedNodeName *string `json:"nominatedNodeName,omitempty"`
|
||||||
HostIP *string `json:"hostIP,omitempty"`
|
HostIP *string `json:"hostIP,omitempty"`
|
||||||
HostIPs []HostIPApplyConfiguration `json:"hostIPs,omitempty"`
|
|
||||||
PodIP *string `json:"podIP,omitempty"`
|
PodIP *string `json:"podIP,omitempty"`
|
||||||
PodIPs []PodIPApplyConfiguration `json:"podIPs,omitempty"`
|
PodIPs []PodIPApplyConfiguration `json:"podIPs,omitempty"`
|
||||||
StartTime *metav1.Time `json:"startTime,omitempty"`
|
StartTime *metav1.Time `json:"startTime,omitempty"`
|
||||||
@ -101,19 +100,6 @@ func (b *PodStatusApplyConfiguration) WithHostIP(value string) *PodStatusApplyCo
|
|||||||
return b
|
return b
|
||||||
}
|
}
|
||||||
|
|
||||||
// WithHostIPs adds the given value to the HostIPs field in the declarative configuration
|
|
||||||
// and returns the receiver, so that objects can be build by chaining "With" function invocations.
|
|
||||||
// If called multiple times, values provided by each call will be appended to the HostIPs field.
|
|
||||||
func (b *PodStatusApplyConfiguration) WithHostIPs(values ...*HostIPApplyConfiguration) *PodStatusApplyConfiguration {
|
|
||||||
for i := range values {
|
|
||||||
if values[i] == nil {
|
|
||||||
panic("nil value passed to WithHostIPs")
|
|
||||||
}
|
|
||||||
b.HostIPs = append(b.HostIPs, *values[i])
|
|
||||||
}
|
|
||||||
return b
|
|
||||||
}
|
|
||||||
|
|
||||||
// WithPodIP sets the PodIP field in the declarative configuration to the given value
|
// WithPodIP sets the PodIP field in the declarative configuration to the given value
|
||||||
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
// and returns the receiver, so that objects can be built by chaining "With" function invocations.
|
||||||
// If called multiple times, the PodIP field is set to the value of the last call.
|
// If called multiple times, the PodIP field is set to the value of the last call.
|
||||||
|
@ -4629,12 +4629,6 @@ var schemaYAML = typed.YAMLObject(`types:
|
|||||||
- name: ip
|
- name: ip
|
||||||
type:
|
type:
|
||||||
scalar: string
|
scalar: string
|
||||||
- name: io.k8s.api.core.v1.HostIP
|
|
||||||
map:
|
|
||||||
fields:
|
|
||||||
- name: ip
|
|
||||||
type:
|
|
||||||
scalar: string
|
|
||||||
- name: io.k8s.api.core.v1.HostPathVolumeSource
|
- name: io.k8s.api.core.v1.HostPathVolumeSource
|
||||||
map:
|
map:
|
||||||
fields:
|
fields:
|
||||||
@ -5895,12 +5889,6 @@ var schemaYAML = typed.YAMLObject(`types:
|
|||||||
- name: hostIP
|
- name: hostIP
|
||||||
type:
|
type:
|
||||||
scalar: string
|
scalar: string
|
||||||
- name: hostIPs
|
|
||||||
type:
|
|
||||||
list:
|
|
||||||
elementType:
|
|
||||||
namedType: io.k8s.api.core.v1.HostIP
|
|
||||||
elementRelationship: associative
|
|
||||||
- name: initContainerStatuses
|
- name: initContainerStatuses
|
||||||
type:
|
type:
|
||||||
list:
|
list:
|
||||||
|
@ -613,8 +613,6 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
|
|||||||
return &applyconfigurationscorev1.GRPCActionApplyConfiguration{}
|
return &applyconfigurationscorev1.GRPCActionApplyConfiguration{}
|
||||||
case corev1.SchemeGroupVersion.WithKind("HostAlias"):
|
case corev1.SchemeGroupVersion.WithKind("HostAlias"):
|
||||||
return &applyconfigurationscorev1.HostAliasApplyConfiguration{}
|
return &applyconfigurationscorev1.HostAliasApplyConfiguration{}
|
||||||
case corev1.SchemeGroupVersion.WithKind("HostIP"):
|
|
||||||
return &applyconfigurationscorev1.HostIPApplyConfiguration{}
|
|
||||||
case corev1.SchemeGroupVersion.WithKind("HostPathVolumeSource"):
|
case corev1.SchemeGroupVersion.WithKind("HostPathVolumeSource"):
|
||||||
return &applyconfigurationscorev1.HostPathVolumeSourceApplyConfiguration{}
|
return &applyconfigurationscorev1.HostPathVolumeSourceApplyConfiguration{}
|
||||||
case corev1.SchemeGroupVersion.WithKind("HTTPGetAction"):
|
case corev1.SchemeGroupVersion.WithKind("HTTPGetAction"):
|
||||||
|
@ -1,198 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright 2022 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 e2enode
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/onsi/ginkgo"
|
|
||||||
"github.com/onsi/gomega"
|
|
||||||
|
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/api/resource"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
|
||||||
"k8s.io/kubernetes/pkg/features"
|
|
||||||
kubefeatures "k8s.io/kubernetes/pkg/features"
|
|
||||||
kubeletconfig "k8s.io/kubernetes/pkg/kubelet/apis/config"
|
|
||||||
"k8s.io/kubernetes/test/e2e/framework"
|
|
||||||
e2enetwork "k8s.io/kubernetes/test/e2e/framework/network"
|
|
||||||
e2enode "k8s.io/kubernetes/test/e2e/framework/node"
|
|
||||||
e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
|
|
||||||
"k8s.io/kubernetes/test/e2e/network/common"
|
|
||||||
imageutils "k8s.io/kubernetes/test/utils/image"
|
|
||||||
netutils "k8s.io/utils/net"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = common.SIGDescribe("Dual Stack Host IP [Feature:PodHostIPs]", func() {
|
|
||||||
f := framework.NewDefaultFramework("dualstack")
|
|
||||||
|
|
||||||
ginkgo.Context("when creating a Pod, it has PodHostIPs feature", func() {
|
|
||||||
tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) {
|
|
||||||
initialConfig.FeatureGates = map[string]bool{
|
|
||||||
string(features.PodHostIPs): false,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
ginkgo.It("should create pod, add host ips is empty", func() {
|
|
||||||
e2eskipper.SkipIfFeatureGateEnabled(kubefeatures.PodHostIPs)
|
|
||||||
|
|
||||||
podName := "pod-dualstack-host-ips"
|
|
||||||
|
|
||||||
pod := &v1.Pod{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: podName,
|
|
||||||
Labels: map[string]string{"test": "dualstack-host-ips"},
|
|
||||||
},
|
|
||||||
Spec: v1.PodSpec{
|
|
||||||
Containers: []v1.Container{
|
|
||||||
{
|
|
||||||
Name: "dualstack-host-ips",
|
|
||||||
Image: imageutils.GetE2EImage(imageutils.Agnhost),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
ginkgo.By("submitting the pod to kubernetes")
|
|
||||||
podClient := f.PodClient()
|
|
||||||
p := podClient.CreateSync(pod)
|
|
||||||
|
|
||||||
gomega.Expect(p.Status.HostIP).ShouldNot(gomega.BeEquivalentTo(""))
|
|
||||||
gomega.Expect(p.Status.HostIPs).Should(gomega.BeNil())
|
|
||||||
|
|
||||||
ginkgo.By("deleting the pod")
|
|
||||||
err := podClient.Delete(context.TODO(), pod.Name, *metav1.NewDeleteOptions(30))
|
|
||||||
framework.ExpectNoError(err, "failed to delete pod")
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.Context("when creating a Pod, it has no PodHostIPs feature", func() {
|
|
||||||
tempSetCurrentKubeletConfig(f, func(initialConfig *kubeletconfig.KubeletConfiguration) {
|
|
||||||
initialConfig.FeatureGates = map[string]bool{
|
|
||||||
string(features.PodHostIPs): true,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
ginkgo.It("should create pod, add ipv6 and ipv4 ip to host ips", func() {
|
|
||||||
|
|
||||||
podName := "pod-dualstack-host-ips"
|
|
||||||
|
|
||||||
pod := &v1.Pod{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: podName,
|
|
||||||
Labels: map[string]string{"test": "dualstack-host-ips"},
|
|
||||||
},
|
|
||||||
Spec: v1.PodSpec{
|
|
||||||
Containers: []v1.Container{
|
|
||||||
{
|
|
||||||
Name: "dualstack-host-ips",
|
|
||||||
Image: imageutils.GetE2EImage(imageutils.Agnhost),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
ginkgo.By("submitting the pod to kubernetes")
|
|
||||||
podClient := f.PodClient()
|
|
||||||
p := podClient.CreateSync(pod)
|
|
||||||
|
|
||||||
gomega.Expect(p.Status.HostIP).ShouldNot(gomega.BeEquivalentTo(""))
|
|
||||||
gomega.Expect(p.Status.HostIPs).ShouldNot(gomega.BeNil())
|
|
||||||
|
|
||||||
// validate first ip in HostIPs is same as HostIP
|
|
||||||
framework.ExpectEqual(p.Status.HostIP, p.Status.HostIPs[0].IP)
|
|
||||||
if len(p.Status.HostIPs) > 1 {
|
|
||||||
// assert 2 host ips belong to different families
|
|
||||||
if netutils.IsIPv4String(p.Status.HostIPs[0].IP) == netutils.IsIPv4String(p.Status.HostIPs[1].IP) {
|
|
||||||
framework.Failf("both internalIPs %s and %s belong to the same families", p.Status.HostIPs[0].IP, p.Status.HostIPs[1].IP)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
nodeList, err := e2enode.GetReadySchedulableNodes(f.ClientSet)
|
|
||||||
framework.ExpectNoError(err)
|
|
||||||
for _, node := range nodeList.Items {
|
|
||||||
if node.Name == p.Spec.NodeName {
|
|
||||||
nodeIPs := []string{}
|
|
||||||
for _, address := range node.Status.Addresses {
|
|
||||||
if address.Type == v1.NodeInternalIP {
|
|
||||||
nodeIPs = append(nodeIPs, address.Address)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
gomega.Expect(p.Status.HostIPs).Should(gomega.Equal(nodeIPs))
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ginkgo.By("deleting the pod")
|
|
||||||
err = podClient.Delete(context.TODO(), pod.Name, *metav1.NewDeleteOptions(30))
|
|
||||||
framework.ExpectNoError(err, "failed to delete pod")
|
|
||||||
})
|
|
||||||
|
|
||||||
ginkgo.It("should provide hostIPs as an env var", func() {
|
|
||||||
podName := "downward-api-" + string(uuid.NewUUID())
|
|
||||||
env := []v1.EnvVar{
|
|
||||||
{
|
|
||||||
Name: "HOST_IPS",
|
|
||||||
ValueFrom: &v1.EnvVarSource{
|
|
||||||
FieldRef: &v1.ObjectFieldSelector{
|
|
||||||
APIVersion: "v1",
|
|
||||||
FieldPath: "status.hostIPs",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
expectations := []string{
|
|
||||||
fmt.Sprintf("HOST_IPS=%v|%v", e2enetwork.RegexIPv4, e2enetwork.RegexIPv6),
|
|
||||||
}
|
|
||||||
|
|
||||||
testDownwardAPI(f, podName, env, expectations)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
func testDownwardAPI(f *framework.Framework, podName string, env []v1.EnvVar, expectations []string) {
|
|
||||||
pod := &v1.Pod{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: podName,
|
|
||||||
Labels: map[string]string{"name": podName},
|
|
||||||
},
|
|
||||||
Spec: v1.PodSpec{
|
|
||||||
Containers: []v1.Container{
|
|
||||||
{
|
|
||||||
Name: "dapi-container",
|
|
||||||
Image: imageutils.GetE2EImage(imageutils.BusyBox),
|
|
||||||
Command: []string{"sh", "-c", "env"},
|
|
||||||
Resources: v1.ResourceRequirements{
|
|
||||||
Requests: v1.ResourceList{
|
|
||||||
v1.ResourceCPU: resource.MustParse("250m"),
|
|
||||||
v1.ResourceMemory: resource.MustParse("32Mi"),
|
|
||||||
},
|
|
||||||
Limits: v1.ResourceList{
|
|
||||||
v1.ResourceCPU: resource.MustParse("1250m"),
|
|
||||||
v1.ResourceMemory: resource.MustParse("64Mi"),
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Env: env,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
RestartPolicy: v1.RestartPolicyNever,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
f.TestContainerOutputRegexp("downward api env vars", pod, 0, expectations)
|
|
||||||
}
|
|
Loading…
Reference in New Issue
Block a user