diff --git a/controllers/nginx_controller.go b/controllers/nginx_controller.go index ffc1f8e0..dc214e85 100644 --- a/controllers/nginx_controller.go +++ b/controllers/nginx_controller.go @@ -33,9 +33,11 @@ import ( ) const ( - gcpNetworkTierAnnotationKey = "cloud.google.com/network-tier" - ociLoadBalancerTLSSecret = "service.beta.kubernetes.io/oci-load-balancer-tls-secret" - ociLoadBalancerSSLPorts = "service.beta.kubernetes.io/oci-load-balancer-ssl-ports" + gcpNetworkTierAnnotationKey = "cloud.google.com/network-tier" + gcpInternalLBSubnetAnnotationKey = "networking.gke.io/internal-load-balancer-subnet" + gcpLBSubnetAnnotationKey = "networking.gke.io/load-balancer-subnet" + ociLoadBalancerTLSSecret = "service.beta.kubernetes.io/oci-load-balancer-tls-secret" + ociLoadBalancerSSLPorts = "service.beta.kubernetes.io/oci-load-balancer-ssl-ports" useHTTPSOverHTTPAnnotation = "nginx.tsuru.io/https-over-http" nginxIpv6GcpAnnotation = "nginx.tsuru.io/allocate-gcp-ipv6" ingressStaticIPAnnotation = "kubernetes.io/ingress.global-static-ip-name" @@ -194,6 +196,16 @@ func (r *NginxReconciler) reconcileService(ctx context.Context, nginx *nginxv1al newService.Annotations[gcpNetworkTierAnnotationKey] = currentService.Annotations[gcpNetworkTierAnnotationKey] } + if newService.Annotations[gcpInternalLBSubnetAnnotationKey] != currentService.Annotations[gcpInternalLBSubnetAnnotationKey] { + r.Log.Info("the GCP internal load balancer subnet of this service cannot be changed, because IP address may change and cause downtime", "nginx", nginx.Name, "namespace", nginx.Namespace) + newService.Annotations[gcpInternalLBSubnetAnnotationKey] = currentService.Annotations[gcpInternalLBSubnetAnnotationKey] + } + + if newService.Annotations[gcpLBSubnetAnnotationKey] != currentService.Annotations[gcpLBSubnetAnnotationKey] { + r.Log.Info("the GCP load balancer subnet of this service cannot be changed, because IP address may change and cause downtime", "nginx", nginx.Name, "namespace", nginx.Namespace) + newService.Annotations[gcpLBSubnetAnnotationKey] = currentService.Annotations[gcpLBSubnetAnnotationKey] + } + newService.ResourceVersion = currentService.ResourceVersion newService.Spec.ClusterIP = currentService.Spec.ClusterIP newService.Spec.HealthCheckNodePort = currentService.Spec.HealthCheckNodePort diff --git a/controllers/nginx_controller_test.go b/controllers/nginx_controller_test.go index dd7f188d..8deb44bd 100644 --- a/controllers/nginx_controller_test.go +++ b/controllers/nginx_controller_test.go @@ -591,6 +591,136 @@ func TestNginxReconciler_reconcileService(t *testing.T) { "Normal ServiceUpdated service updated successfully", }, }, + { + name: "when updating the nginx service, must not change the GCP internal-load-balancer-subnet annotation", + nginx: &v1alpha1.Nginx{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "extensions.tsuru.io/v1alpha1", + Kind: "Nginx", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-nginx", + Namespace: "default", + }, + Spec: v1alpha1.NginxSpec{ + Service: &v1alpha1.NginxService{ + Type: corev1.ServiceTypeClusterIP, + Annotations: map[string]string{ + "networking.gke.io/internal-load-balancer-subnet": "subnet-new", + }, + }, + }, + }, + service: &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Service", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-nginx-service", + Namespace: "default", + Annotations: map[string]string{ + "networking.gke.io/internal-load-balancer-subnet": "subnet-original", + }, + Labels: map[string]string{}, + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + ExternalTrafficPolicy: corev1.ServiceExternalTrafficPolicyTypeCluster, + ClusterIP: "10.1.1.10", + HealthCheckNodePort: int32(43123), + Ports: []corev1.ServicePort{ + { + Name: "https", + TargetPort: intstr.FromString("https"), + Protocol: corev1.ProtocolTCP, + Port: int32(443), + NodePort: int32(30667), + }, + { + Name: "http", + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromString("http"), + Port: int32(80), + NodePort: int32(30666), + }, + }, + }, + }, + assertion: func(t *testing.T, err error, got *corev1.Service) { + assert.NoError(t, err) + assert.NotNil(t, got) + assert.Equal(t, "subnet-original", got.Annotations["networking.gke.io/internal-load-balancer-subnet"]) + }, + expectedEvents: []string{ + "Normal ServiceUpdated service updated successfully", + }, + }, + { + name: "when updating the nginx service, must not change the GCP load-balancer-subnet annotation", + nginx: &v1alpha1.Nginx{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "extensions.tsuru.io/v1alpha1", + Kind: "Nginx", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-nginx", + Namespace: "default", + }, + Spec: v1alpha1.NginxSpec{ + Service: &v1alpha1.NginxService{ + Type: corev1.ServiceTypeClusterIP, + Annotations: map[string]string{ + "networking.gke.io/load-balancer-subnet": "subnet-new", + }, + }, + }, + }, + service: &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Service", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-nginx-service", + Namespace: "default", + Annotations: map[string]string{ + "networking.gke.io/load-balancer-subnet": "subnet-original", + }, + Labels: map[string]string{}, + }, + Spec: corev1.ServiceSpec{ + Type: corev1.ServiceTypeLoadBalancer, + ExternalTrafficPolicy: corev1.ServiceExternalTrafficPolicyTypeCluster, + ClusterIP: "10.1.1.10", + HealthCheckNodePort: int32(43123), + Ports: []corev1.ServicePort{ + { + Name: "https", + TargetPort: intstr.FromString("https"), + Protocol: corev1.ProtocolTCP, + Port: int32(443), + NodePort: int32(30667), + }, + { + Name: "http", + Protocol: corev1.ProtocolTCP, + TargetPort: intstr.FromString("http"), + Port: int32(80), + NodePort: int32(30666), + }, + }, + }, + }, + assertion: func(t *testing.T, err error, got *corev1.Service) { + assert.NoError(t, err) + assert.NotNil(t, got) + assert.Equal(t, "subnet-original", got.Annotations["networking.gke.io/load-balancer-subnet"]) + }, + expectedEvents: []string{ + "Normal ServiceUpdated service updated successfully", + }, + }, { name: "when setting OCI load balancer type with TLS annotations, should set the OCI load balancer with proper secret annotation", nginx: &v1alpha1.Nginx{