mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-29 06:27:05 +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 {
|
||||
allErrs := ValidateObjectMetaUpdate(&service.ObjectMeta, &oldService.ObjectMeta, field.NewPath("metadata"))
|
||||
|
||||
if api.IsServiceIPSet(oldService) {
|
||||
allErrs = append(allErrs, ValidateImmutableField(service.Spec.ClusterIP, oldService.Spec.ClusterIP, field.NewPath("spec", "clusterIP"))...)
|
||||
// ClusterIP should be immutable for services using it (every type other than ExternalName)
|
||||
// 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
|
||||
|
@ -6519,6 +6519,242 @@ func TestValidateServiceUpdate(t *testing.T) {
|
||||
},
|
||||
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 {
|
||||
|
@ -100,6 +100,7 @@ func TestUpdate(t *testing.T) {
|
||||
object := obj.(*api.Service)
|
||||
object.Spec = api.ServiceSpec{
|
||||
Selector: map[string]string{"bar": "baz2"},
|
||||
ClusterIP: "None",
|
||||
SessionAffinity: api.ServiceAffinityNone,
|
||||
Type: api.ServiceTypeClusterIP,
|
||||
Ports: []api.ServicePort{{
|
||||
|
Loading…
Reference in New Issue
Block a user