diff --git a/pkg/controllers/resources/ingresses/syncer.go b/pkg/controllers/resources/ingresses/syncer.go index 6add86358c..0d1a07fe91 100644 --- a/pkg/controllers/resources/ingresses/syncer.go +++ b/pkg/controllers/resources/ingresses/syncer.go @@ -3,6 +3,7 @@ package ingresses import ( "strings" + "github.com/loft-sh/vcluster/pkg/controllers/resources/services" synccontext "github.com/loft-sh/vcluster/pkg/controllers/syncer/context" "github.com/loft-sh/vcluster/pkg/controllers/syncer/translator" syncertypes "github.com/loft-sh/vcluster/pkg/types" @@ -14,8 +15,9 @@ import ( ) func NewSyncer(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { + excludedAnnotations := []string{services.RancherPublicEndpointsAnnotation} return &ingressSyncer{ - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "ingress", &networkingv1.Ingress{}), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "ingress", &networkingv1.Ingress{}, excludedAnnotations...), }, nil } diff --git a/pkg/controllers/resources/ingresses/syncer_test.go b/pkg/controllers/resources/ingresses/syncer_test.go index ad52f0b373..f89ebd373d 100644 --- a/pkg/controllers/resources/ingresses/syncer_test.go +++ b/pkg/controllers/resources/ingresses/syncer_test.go @@ -430,6 +430,81 @@ func TestSync(t *testing.T) { err = syncCtx.PhysicalClient.Get(syncCtx.Context, types.NamespacedName{Name: createdIngress.Name, Namespace: createdIngress.Namespace}, pIngress) assert.NilError(t, err) + _, err = syncer.(*ingressSyncer).Sync(syncCtx, pIngress, vIngress) + assert.NilError(t, err) + }, + }, + { + Name: "Exclude Rancher managed annotations from syncing", + InitialVirtualState: []runtime.Object{ + &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: baseIngress.Name, + Namespace: baseIngress.Namespace, + Labels: baseIngress.Labels, + Annotations: map[string]string{ + "nginx.ingress.kubernetes.io/auth-secret": "my-secret", + "nginx.ingress.kubernetes.io/auth-tls-secret": baseIngress.Namespace + "/my-secret", + "field.cattle.io/publicEndpoints": `[{"addresses":["192.168.0.10"],"port":80,"protocol":"HTTP","serviceName":"default:nginx","ingressName":"default:test-ingress","hostname":"my-ingress-endpoint.com","path":"/","allNodes":false}]`, + }, + }, + }, + }, + InitialPhysicalState: []runtime.Object{ + &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: createdIngress.Name, + Namespace: createdIngress.Namespace, + Labels: createdIngress.Labels, + }, + }, + }, + ExpectedVirtualState: map[schema.GroupVersionKind][]runtime.Object{ + networkingv1.SchemeGroupVersion.WithKind("Ingress"): { + &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: baseIngress.Name, + Namespace: baseIngress.Namespace, + Labels: baseIngress.Labels, + Annotations: map[string]string{ + "nginx.ingress.kubernetes.io/auth-secret": "my-secret", + "nginx.ingress.kubernetes.io/auth-tls-secret": baseIngress.Namespace + "/my-secret", + "field.cattle.io/publicEndpoints": `[{"addresses":["192.168.0.10"],"port":80,"protocol":"HTTP","serviceName":"default:nginx","ingressName":"default:test-ingress","hostname":"my-ingress-endpoint.com","path":"/","allNodes":false}]`, + }, + }, + }, + }, + }, + ExpectedPhysicalState: map[schema.GroupVersionKind][]runtime.Object{ + networkingv1.SchemeGroupVersion.WithKind("Ingress"): { + &networkingv1.Ingress{ + ObjectMeta: metav1.ObjectMeta{ + Name: createdIngress.Name, + Namespace: createdIngress.Namespace, + Labels: createdIngress.Labels, + Annotations: map[string]string{ + "nginx.ingress.kubernetes.io/auth-secret": translate.Default.PhysicalName("my-secret", baseIngress.Namespace), + "nginx.ingress.kubernetes.io/auth-tls-secret": createdIngress.Namespace + "/" + translate.Default.PhysicalName("my-secret", baseIngress.Namespace), + "vcluster.loft.sh/managed-annotations": "nginx.ingress.kubernetes.io/auth-secret\nnginx.ingress.kubernetes.io/auth-tls-secret", + "vcluster.loft.sh/object-name": baseIngress.Name, + "vcluster.loft.sh/object-namespace": baseIngress.Namespace, + translate.UIDAnnotation: "", + }, + }, + }, + }, + }, + Sync: func(registerContext *synccontext.RegisterContext) { + syncCtx, syncer := generictesting.FakeStartSyncer(t, registerContext, NewSyncer) + + vIngress := &networkingv1.Ingress{} + err := syncCtx.VirtualClient.Get(syncCtx.Context, types.NamespacedName{Name: baseIngress.Name, Namespace: baseIngress.Namespace}, vIngress) + assert.NilError(t, err) + + pIngress := &networkingv1.Ingress{} + err = syncCtx.PhysicalClient.Get(syncCtx.Context, types.NamespacedName{Name: createdIngress.Name, Namespace: createdIngress.Namespace}, pIngress) + assert.NilError(t, err) + _, err = syncer.(*ingressSyncer).Sync(syncCtx, pIngress, vIngress) assert.NilError(t, err) }, diff --git a/pkg/controllers/resources/services/syncer.go b/pkg/controllers/resources/services/syncer.go index e014819689..44fb069b70 100644 --- a/pkg/controllers/resources/services/syncer.go +++ b/pkg/controllers/resources/services/syncer.go @@ -19,14 +19,17 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" ) -var ServiceBlockDeletion = "vcluster.loft.sh/block-deletion" +var ( + ServiceBlockDeletion = "vcluster.loft.sh/block-deletion" + RancherPublicEndpointsAnnotation = "field.cattle.io/publicEndpoints" +) func New(ctx *synccontext.RegisterContext) (syncertypes.Object, error) { return &serviceSyncer{ // exclude "field.cattle.io/publicEndpoints" annotation used by Rancher, // because if it is also installed in the host cluster, it will be // overriding it, which would cause endless updates back and forth. - NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "service", &corev1.Service{}, "field.cattle.io/publicEndpoints"), + NamespacedTranslator: translator.NewNamespacedTranslator(ctx, "service", &corev1.Service{}, RancherPublicEndpointsAnnotation), serviceName: ctx.Options.ServiceName, }, nil