mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 22:46:12 +00:00
Merge pull request #34094 from nebril/hless-to-nonhless-ip
Automatic merge from submit-queue Deny service ClusterIP update from `None` **What this PR does / why we need it**: Headless service should not be transformed into a service with ClusterIP, therefore update of this field if it's set to `None` is disallowed. **Which issue this PR fixes** *(optional, in `fixes #<issue number>(, #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #33029 **Release note**: ```release-note Changing service ClusterIP from `None` is not allowed anymore. ```
This commit is contained in:
commit
bdaf502ff4
@ -2635,8 +2635,12 @@ func validateServiceAnnotations(service *api.Service, oldService *api.Service) (
|
|||||||
func ValidateServiceUpdate(service, oldService *api.Service) field.ErrorList {
|
func ValidateServiceUpdate(service, oldService *api.Service) field.ErrorList {
|
||||||
allErrs := ValidateObjectMetaUpdate(&service.ObjectMeta, &oldService.ObjectMeta, field.NewPath("metadata"))
|
allErrs := ValidateObjectMetaUpdate(&service.ObjectMeta, &oldService.ObjectMeta, field.NewPath("metadata"))
|
||||||
|
|
||||||
if api.IsServiceIPSet(oldService) {
|
// ClusterIP should be immutable for services using it (every type other than ExternalName)
|
||||||
allErrs = append(allErrs, ValidateImmutableField(service.Spec.ClusterIP, oldService.Spec.ClusterIP, field.NewPath("spec", "clusterIP"))...)
|
// which do not have ClusterIP assigned yet (empty string value)
|
||||||
|
if service.Spec.Type != api.ServiceTypeExternalName {
|
||||||
|
if oldService.Spec.Type != api.ServiceTypeExternalName && oldService.Spec.ClusterIP != "" {
|
||||||
|
allErrs = append(allErrs, ValidateImmutableField(service.Spec.ClusterIP, oldService.Spec.ClusterIP, field.NewPath("spec", "clusterIP"))...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(freehan): allow user to update loadbalancerSourceRanges
|
// TODO(freehan): allow user to update loadbalancerSourceRanges
|
||||||
|
@ -6519,6 +6519,242 @@ func TestValidateServiceUpdate(t *testing.T) {
|
|||||||
},
|
},
|
||||||
numErrs: 0,
|
numErrs: 0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: "`None` ClusterIP cannot be changed",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.ClusterIP = "None"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "`None` ClusterIP cannot be removed",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.ClusterIP = "None"
|
||||||
|
newSvc.Spec.ClusterIP = ""
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with ClusterIP type cannot change its set ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with ClusterIP type can change its empty ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = ""
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with ClusterIP type cannot change its set ClusterIP when changing type to NodePort",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with ClusterIP type can change its empty ClusterIP when changing type to NodePort",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = ""
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with ClusterIP type cannot change its ClusterIP when changing type to LoadBalancer",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with ClusterIP type can change its empty ClusterIP when changing type to LoadBalancer",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = ""
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with NodePort type cannot change its set ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with NodePort type can change its empty ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = ""
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with NodePort type cannot change its set ClusterIP when changing type to ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with NodePort type can change its empty ClusterIP when changing type to ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = ""
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with NodePort type cannot change its set ClusterIP when changing type to LoadBalancer",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with NodePort type can change its empty ClusterIP when changing type to LoadBalancer",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = ""
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with LoadBalancer type cannot change its set ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with LoadBalancer type can change its empty ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = ""
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with LoadBalancer type cannot change its set ClusterIP when changing type to ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with LoadBalancer type can change its empty ClusterIP when changing type to ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = ""
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with LoadBalancer type cannot change its set ClusterIP when changing type to NodePort",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with LoadBalancer type can change its empty ClusterIP when changing type to NodePort",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeLoadBalancer
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeNodePort
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = ""
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with ExternalName type can change its empty ClusterIP when changing type to ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeExternalName
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = ""
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "Service with ExternalName type can change its set ClusterIP when changing type to ClusterIP",
|
||||||
|
tweakSvc: func(oldSvc, newSvc *api.Service) {
|
||||||
|
oldSvc.Spec.Type = api.ServiceTypeExternalName
|
||||||
|
newSvc.Spec.Type = api.ServiceTypeClusterIP
|
||||||
|
|
||||||
|
oldSvc.Spec.ClusterIP = "1.2.3.4"
|
||||||
|
newSvc.Spec.ClusterIP = "1.2.3.5"
|
||||||
|
},
|
||||||
|
numErrs: 0,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
@ -100,6 +100,7 @@ func TestUpdate(t *testing.T) {
|
|||||||
object := obj.(*api.Service)
|
object := obj.(*api.Service)
|
||||||
object.Spec = api.ServiceSpec{
|
object.Spec = api.ServiceSpec{
|
||||||
Selector: map[string]string{"bar": "baz2"},
|
Selector: map[string]string{"bar": "baz2"},
|
||||||
|
ClusterIP: "None",
|
||||||
SessionAffinity: api.ServiceAffinityNone,
|
SessionAffinity: api.ServiceAffinityNone,
|
||||||
Type: api.ServiceTypeClusterIP,
|
Type: api.ServiceTypeClusterIP,
|
||||||
Ports: []api.ServicePort{{
|
Ports: []api.ServicePort{{
|
||||||
|
Loading…
Reference in New Issue
Block a user