diff --git a/controllers/nginx_controller.go b/controllers/nginx_controller.go index 5b187a5f..955d7bbc 100644 --- a/controllers/nginx_controller.go +++ b/controllers/nginx_controller.go @@ -34,6 +34,8 @@ 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" ) // NginxReconciler reconciles a Nginx object @@ -202,6 +204,13 @@ func (r *NginxReconciler) reconcileService(ctx context.Context, nginx *nginxv1al } } + if newService.Annotations[ociLoadBalancerSSLPorts] != "" { + if len(nginx.Spec.TLS) > 0 { + secretName := getFirstTLSSortedBySecretName(nginx.Spec.TLS) + newService.Annotations[ociLoadBalancerTLSSecret] = fmt.Sprintf("%s/%s", nginx.Namespace, secretName) + } + } + if newService.Spec.Type == corev1.ServiceTypeNodePort || newService.Spec.Type == corev1.ServiceTypeLoadBalancer { // avoid nodeport reallocation preserving the current ones for _, currentPort := range currentService.Spec.Ports { @@ -458,3 +467,15 @@ func (r *NginxReconciler) shouldManageNginx(nginx *v1alpha1.Nginx) bool { return r.AnnotationFilter.Matches(labels.Set(nginx.Annotations)) } + +func getFirstTLSSortedBySecretName(tls []nginxv1alpha1.NginxTLS) string { + if len(tls) == 0 { + return "" + } + + sort.Slice(tls, func(i, j int) bool { + return tls[i].SecretName < tls[j].SecretName + }) + + return tls[0].SecretName +} diff --git a/controllers/nginx_controller_test.go b/controllers/nginx_controller_test.go index 71a81840..d9d0662f 100644 --- a/controllers/nginx_controller_test.go +++ b/controllers/nginx_controller_test.go @@ -590,6 +590,133 @@ func TestNginxReconciler_reconcileService(t *testing.T) { "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{ + 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{ + ociLoadBalancerSSLPorts: "443", + }, + }, + TLS: []v1alpha1.NginxTLS{{SecretName: "my-secret-2"}, {SecretName: "my-secret-1"}}, + }, + }, + service: &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Service", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-nginx-service", + Namespace: "default", + Annotations: map[string]string{}, + 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, "default/my-secret-1", got.Annotations[ociLoadBalancerTLSSecret]) + }, + expectedEvents: []string{ + "Normal ServiceUpdated service updated successfully", + }, + }, + { + name: "when setting OCI load balancer type with TLS annotations do nothing if no secret is provided", + 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{ + ociLoadBalancerSSLPorts: "443", + }, + }, + }, + }, + service: &corev1.Service{ + TypeMeta: metav1.TypeMeta{ + APIVersion: "v1", + Kind: "Service", + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "my-nginx-service", + Namespace: "default", + Annotations: map[string]string{}, + 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, "", got.Annotations[ociLoadBalancerTLSSecret]) + }, + expectedEvents: []string{ + "Normal ServiceUpdated service updated successfully", + }, + }, { name: "when updating then nginx service, should keep resource finalizers", nginx: &v1alpha1.Nginx{