Revert "Field status.hostIPs added for Pod (#101566)"

This reverts commit 61b3c028ba.
This commit is contained in:
Maciej Wyrzuc 2022-03-30 12:50:48 +00:00
parent e54ff8a7ff
commit 1108bed763
32 changed files with 1072 additions and 2068 deletions

View File

@ -6720,16 +6720,6 @@
},
"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": {
"description": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.",
"properties": {
@ -8396,10 +8386,10 @@
"type": "object"
},
"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": {
"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"
}
},
@ -8769,19 +8759,9 @@
"type": "array"
},
"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"
},
"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": {
"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": {
@ -8809,7 +8789,7 @@
"type": "string"
},
"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"
},
"podIPs": {

View File

@ -2609,16 +2609,6 @@
},
"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": {
"description": "Represents a host path mapped into a pod. Host path volumes do not support ownership management or SELinux relabeling.",
"properties": {
@ -4854,10 +4844,10 @@
"type": "object"
},
"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": {
"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"
}
},
@ -5339,24 +5329,9 @@
"type": "array"
},
"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"
},
"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": {
"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": {
@ -5389,7 +5364,7 @@
"type": "string"
},
"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"
},
"podIPs": {

View File

@ -434,8 +434,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po
AllowExpandedDNSConfig: utilfeature.DefaultFeatureGate.Enabled(features.ExpandedDNSConfig) || haveSameExpandedDNSConfig(podSpec, oldPodSpec),
// Allow pod spec to use OS field
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
AllowSysctlRegexContainSlash: false,
}
@ -456,9 +454,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po
// if old spec has OS field set, we must allow it
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
opts.AllowIndivisibleHugePagesValues = usesIndivisibleHugePagesValues(oldPodSpec)
@ -475,57 +470,6 @@ func GetValidationOptionsFromPodSpecAndMeta(podSpec, oldPodSpec *api.PodSpec, po
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.
func GetValidationOptionsFromPodTemplate(podTemplate, oldPodTemplate *api.PodTemplateSpec) apivalidation.PodValidationOptions {
var newPodSpec, oldPodSpec *api.PodSpec
@ -568,39 +512,19 @@ func DropDisabledTemplateFields(podTemplate, oldPodTemplate *api.PodTemplateSpec
func DropDisabledPodFields(pod, oldPod *api.Pod) {
var (
podSpec *api.PodSpec
podStatus *api.PodStatus
podAnnotations map[string]string
oldPodSpec *api.PodSpec
oldPodStatus *api.PodStatus
oldPodAnnotations map[string]string
)
if pod != nil {
podSpec = &pod.Spec
podAnnotations = pod.Annotations
podStatus = &pod.Status
}
if oldPod != nil {
oldPodSpec = &oldPod.Spec
oldPodAnnotations = oldPod.Annotations
oldPodStatus = &oldPod.Status
}
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.

View File

@ -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
}

View File

@ -91,10 +91,6 @@ var Funcs = func(codecs runtimeserializer.CodecFactory) []interface{} {
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) {
statuses := []core.PodPhase{core.PodPending, core.PodRunning, core.PodFailed, core.PodUnknown}
*j = statuses[c.Rand.Intn(len(statuses))]

View File

@ -88,7 +88,6 @@ func ConvertDownwardAPIFieldLabel(version, label, value string) (string, string,
"spec.schedulerName",
"status.phase",
"status.hostIP",
"status.hostIPs",
"status.podIP",
"status.podIPs":
return label, value, nil

View File

@ -3212,14 +3212,10 @@ type PodDNSConfigOption struct {
}
// 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 {
// 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
}
@ -3360,22 +3356,9 @@ type PodStatus struct {
// give the resources on this node to a higher priority pod that is created after preemption.
// +optional
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
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
// one value for each of IPv4 and IPv6.
// +optional

View File

@ -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
}
@ -294,11 +283,6 @@ func Convert_core_PodStatus_To_v1_PodStatus(in *core.PodStatus, out *v1.PodStatu
if len(in.PodIPs) > 0 {
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
}

View File

@ -712,16 +712,6 @@ func RegisterConversions(s *runtime.Scheme) error {
}); err != nil {
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 {
return Convert_v1_HostPathVolumeSource_To_core_HostPathVolumeSource(a.(*v1.HostPathVolumeSource), b.(*core.HostPathVolumeSource), scope)
}); 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)
}
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 {
out.Path = in.Path
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.NominatedNodeName = in.NominatedNodeName
out.HostIP = in.HostIP
out.HostIPs = *(*[]core.HostIP)(unsafe.Pointer(&in.HostIPs))
// WARNING: in.PodIP requires manual conversion: does not exist in peer-type
out.PodIPs = *(*[]core.PodIP)(unsafe.Pointer(&in.PodIPs))
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.NominatedNodeName = in.NominatedNodeName
out.HostIP = in.HostIP
out.HostIPs = *(*[]v1.HostIP)(unsafe.Pointer(&in.HostIPs))
out.PodIPs = *(*[]v1.PodIP)(unsafe.Pointer(&in.PodIPs))
out.StartTime = (*metav1.Time)(unsafe.Pointer(in.StartTime))
out.QOSClass = v1.PodQOSClass(in.QOSClass)

View File

@ -1044,7 +1044,6 @@ func validateDownwardAPIVolumeFile(file *core.DownwardAPIVolumeFile, fldPath *fi
if file.ResourceFieldRef != nil {
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 {
localValidContainerResourceFieldPathPrefixes := validContainerResourceFieldPathPrefixes
if opts.AllowDownwardAPIHugePages {
@ -2330,10 +2329,8 @@ var validEnvDownwardAPIFieldPathExpressions = sets.NewString(
"spec.nodeName",
"spec.serviceAccountName",
"status.hostIP",
"status.hostIPs",
"status.podIP",
"status.podIPs",
)
"status.podIPs")
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 {
numSources++
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 {
numSources++
@ -2427,16 +2423,6 @@ func validateObjectFieldSelector(fs *core.ObjectFieldSelector, expressions *sets
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 {
allErrs := field.ErrorList{}
@ -3429,8 +3415,6 @@ type PodValidationOptions struct {
AllowExpandedDNSConfig bool
// Allow OSField to be set in the pod spec
AllowOSField bool
// Allow pod spec to use status.hostIPs in downward API
AllowHostIPsField bool
// Allow sysctl name to contain a slash
AllowSysctlRegexContainSlash bool
}

View File

@ -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",
@ -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",
@ -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 {
@ -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)
}
})
}
}

View File

@ -1802,22 +1802,6 @@ func (in *HostAlias) DeepCopy() *HostAlias {
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.
func (in *HostPathVolumeSource) DeepCopyInto(out *HostPathVolumeSource) {
*out = *in
@ -3990,11 +3974,6 @@ func (in *PodStatus) DeepCopyInto(out *PodStatus) {
(*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 {
in, out := &in.PodIPs, &out.PodIPs
*out = make([]PodIP, len(*in))

View File

@ -412,13 +412,6 @@ const (
// Enables ipv6 dual stack
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
// kep: http://kep.k8s.io/752
// 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
PodOverhead: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.26
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
EndpointSliceProxying: {Default: true, PreRelease: featuregate.GA, LockToDefault: true}, // remove in 1.25
EndpointSliceTerminatingCondition: {Default: true, PreRelease: featuregate.Beta},

View File

@ -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.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.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.ISCSIPersistentVolumeSource": schema_k8sio_api_core_v1_ISCSIPersistentVolumeSource(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 {
return common.OpenAPIDefinition{
Schema: spec.Schema{
@ -21416,12 +21395,12 @@ func schema_k8sio_api_core_v1_PodIP(ref common.ReferenceCallback) common.OpenAPI
return common.OpenAPIDefinition{
Schema: spec.Schema{
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"},
Properties: map[string]spec.Schema{
"ip": {
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"},
Format: "",
},
@ -22265,35 +22244,14 @@ func schema_k8sio_api_core_v1_PodStatus(ref common.ReferenceCallback) common.Ope
},
"hostIP": {
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"},
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": {
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"},
Format: "",
},
@ -22377,7 +22335,7 @@ func schema_k8sio_api_core_v1_PodStatus(ref common.ReferenceCallback) common.Ope
},
},
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"},
}
}

View File

@ -826,19 +826,6 @@ func (kl *Kubelet) podFieldSelectorRuntimeValue(fs *v1.ObjectFieldSelector, pod
return "", err
}
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":
return podIP, nil
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)
} else {
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,
// other than that if the node becomes dual-stack, we add the secondary IP.
if kubecontainer.IsHostNetworkPod(pod) {

View File

@ -38,10 +38,8 @@ import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/diff"
utilfeature "k8s.io/apiserver/pkg/util/feature"
core "k8s.io/client-go/testing"
"k8s.io/client-go/tools/record"
featuregatetesting "k8s.io/component-base/featuregate/testing"
netutils "k8s.io/utils/net"
// TODO: remove this import if
@ -49,7 +47,6 @@ import (
// to "v1"?
_ "k8s.io/kubernetes/pkg/apis/core/install"
"k8s.io/kubernetes/pkg/features"
kubecontainer "k8s.io/kubernetes/pkg/kubelet/container"
containertest "k8s.io/kubernetes/pkg/kubelet/container/testing"
"k8s.io/kubernetes/pkg/kubelet/cri/streaming/portforward"
@ -2473,10 +2470,6 @@ func TestConvertToAPIContainerStatuses(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{
NodeName: "machine",
Containers: []v1.Container{
@ -2517,7 +2510,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
expected: v1.PodStatus{
Phase: v1.PodRunning,
HostIP: "127.0.0.1",
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
QOSClass: v1.PodQOSBestEffort,
Conditions: []v1.PodCondition{
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
@ -2552,7 +2544,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
expected: v1.PodStatus{
Phase: v1.PodRunning,
HostIP: "127.0.0.1",
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
QOSClass: v1.PodQOSBestEffort,
Conditions: []v1.PodCondition{
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
@ -2588,7 +2579,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
expected: v1.PodStatus{
Phase: v1.PodSucceeded,
HostIP: "127.0.0.1",
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
QOSClass: v1.PodQOSBestEffort,
Conditions: []v1.PodCondition{
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
@ -2628,7 +2618,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
expected: v1.PodStatus{
Phase: v1.PodSucceeded,
HostIP: "127.0.0.1",
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
QOSClass: v1.PodQOSBestEffort,
Conditions: []v1.PodCondition{
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
@ -2677,7 +2666,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
expected: v1.PodStatus{
Phase: v1.PodSucceeded,
HostIP: "127.0.0.1",
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
QOSClass: v1.PodQOSBestEffort,
Conditions: []v1.PodCondition{
{Type: v1.PodInitialized, Status: v1.ConditionTrue, Reason: "PodCompleted"},
@ -2715,7 +2703,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
expected: v1.PodStatus{
Phase: v1.PodPending,
HostIP: "127.0.0.1",
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
QOSClass: v1.PodQOSBestEffort,
Conditions: []v1.PodCondition{
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
@ -2765,7 +2752,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
Reason: "Test",
Message: "test",
HostIP: "127.0.0.1",
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
QOSClass: v1.PodQOSBestEffort,
Conditions: []v1.PodCondition{
{Type: v1.PodInitialized, Status: v1.ConditionTrue},
@ -2819,7 +2805,6 @@ func Test_generateAPIPodStatus(t *testing.T) {
expected: v1.PodStatus{
Phase: v1.PodRunning,
HostIP: "127.0.0.1",
HostIPs: []v1.HostIP{{IP: "127.0.0.1"}},
QOSClass: v1.PodQOSBestEffort,
Conditions: []v1.PodCondition{
{Type: v1.PodInitialized, Status: v1.ConditionTrue},

File diff suppressed because it is too large Load Diff

View File

@ -1767,12 +1767,6 @@ message HostAlias {
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.
// Host path volumes do not support ownership management or SELinux relabeling.
message HostPathVolumeSource {
@ -3236,9 +3230,11 @@ message PodExecOptions {
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 {
// 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;
}
@ -3778,24 +3774,11 @@ message PodStatus {
// +optional
optional string nominatedNodeName = 11;
// 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
// IP address of the host to which the pod is assigned. Empty if not yet scheduled.
// +optional
optional string hostIP = 5;
// 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
repeated HostIP hostIPs = 14;
// podIP address allocated to the pod. Routable at least within the cluster.
// IP address allocated to the pod. Routable at least within the cluster.
// Empty if not yet allocated.
// +optional
optional string podIP = 6;

View File

@ -3605,15 +3605,11 @@ type PodDNSConfigOption struct {
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 {
// IP is the IP address 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 is an IP address (IPv4 or IPv6) assigned to the pod
IP string `json:"ip,omitempty" protobuf:"bytes,1,opt,name=ip"`
}
@ -3834,24 +3830,10 @@ type PodStatus struct {
// +optional
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.
// 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
// IP address of the host to which the pod is assigned. Empty if not yet scheduled.
// +optional
HostIP string `json:"hostIP,omitempty" protobuf:"bytes,5,opt,name=hostIP"`
// 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.
// IP address allocated to the pod. Routable at least within the cluster.
// Empty if not yet allocated.
// +optional
PodIP string `json:"podIP,omitempty" protobuf:"bytes,6,opt,name=podIP"`

View File

@ -825,15 +825,6 @@ func (HostAlias) SwaggerDoc() map[string]string {
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{
"": "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",
@ -1543,8 +1534,8 @@ func (PodExecOptions) SwaggerDoc() map[string]string {
}
var map_PodIP = map[string]string{
"": "PodIP address information for entries in the (plural) PodIPs field.",
"ip": "IP is the IP address assigned to the pod",
"": "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 an IP address (IPv4 or IPv6) assigned to the pod",
}
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.",
"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.",
"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",
"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": "podIP address allocated to the pod. Routable at least within the cluster. Empty if not yet allocated.",
"hostIP": "IP address of the host to which the pod is assigned. Empty if not yet scheduled.",
"podIP": "IP 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.",
"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",

View File

@ -1802,22 +1802,6 @@ func (in *HostAlias) DeepCopy() *HostAlias {
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.
func (in *HostPathVolumeSource) DeepCopyInto(out *HostPathVolumeSource) {
*out = *in
@ -3988,11 +3972,6 @@ func (in *PodStatus) DeepCopyInto(out *PodStatus) {
(*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 {
in, out := &in.PodIPs, &out.PodIPs
*out = make([]PodIP, len(*in))

View File

@ -1582,11 +1582,6 @@
"reason": "reasonValue",
"nominatedNodeName": "nominatedNodeNameValue",
"hostIP": "hostIPValue",
"hostIPs": [
{
"ip": "ipValue"
}
],
"podIP": "podIPValue",
"podIPs": [
{

View File

@ -1159,8 +1159,6 @@ status:
message: messageValue
reason: reasonValue
hostIP: hostIPValue
hostIPs:
- ip: ipValue
initContainerStatuses:
- containerID: containerIDValue
image: imageValue

View File

@ -60,11 +60,6 @@
"reason": "reasonValue",
"nominatedNodeName": "nominatedNodeNameValue",
"hostIP": "hostIPValue",
"hostIPs": [
{
"ip": "ipValue"
}
],
"podIP": "podIPValue",
"podIPs": [
{

View File

@ -114,8 +114,6 @@ status:
message: messageValue
reason: reasonValue
hostIP: hostIPValue
hostIPs:
- ip: ipValue
initContainerStatuses:
- containerID: containerIDValue
image: imageValue

View File

@ -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
}

View File

@ -32,7 +32,6 @@ type PodStatusApplyConfiguration struct {
Reason *string `json:"reason,omitempty"`
NominatedNodeName *string `json:"nominatedNodeName,omitempty"`
HostIP *string `json:"hostIP,omitempty"`
HostIPs []HostIPApplyConfiguration `json:"hostIPs,omitempty"`
PodIP *string `json:"podIP,omitempty"`
PodIPs []PodIPApplyConfiguration `json:"podIPs,omitempty"`
StartTime *metav1.Time `json:"startTime,omitempty"`
@ -101,19 +100,6 @@ func (b *PodStatusApplyConfiguration) WithHostIP(value string) *PodStatusApplyCo
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
// 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.

View File

@ -4629,12 +4629,6 @@ var schemaYAML = typed.YAMLObject(`types:
- name: ip
type:
scalar: string
- name: io.k8s.api.core.v1.HostIP
map:
fields:
- name: ip
type:
scalar: string
- name: io.k8s.api.core.v1.HostPathVolumeSource
map:
fields:
@ -5895,12 +5889,6 @@ var schemaYAML = typed.YAMLObject(`types:
- name: hostIP
type:
scalar: string
- name: hostIPs
type:
list:
elementType:
namedType: io.k8s.api.core.v1.HostIP
elementRelationship: associative
- name: initContainerStatuses
type:
list:

View File

@ -613,8 +613,6 @@ func ForKind(kind schema.GroupVersionKind) interface{} {
return &applyconfigurationscorev1.GRPCActionApplyConfiguration{}
case corev1.SchemeGroupVersion.WithKind("HostAlias"):
return &applyconfigurationscorev1.HostAliasApplyConfiguration{}
case corev1.SchemeGroupVersion.WithKind("HostIP"):
return &applyconfigurationscorev1.HostIPApplyConfiguration{}
case corev1.SchemeGroupVersion.WithKind("HostPathVolumeSource"):
return &applyconfigurationscorev1.HostPathVolumeSourceApplyConfiguration{}
case corev1.SchemeGroupVersion.WithKind("HTTPGetAction"):

View File

@ -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)
}