diff --git a/gslb/gslbutils/gslbutils.go b/gslb/gslbutils/gslbutils.go index e1c52f52..1ba45776 100644 --- a/gslb/gslbutils/gslbutils.go +++ b/gslb/gslbutils/gslbutils.go @@ -816,7 +816,8 @@ func GetDefaultPKI(aviClient *clients.AviClient) *string { } const ( - VSAnnotation = "ako.vmware.com/host-fqdn-vs-uuid-map" - ControllerAnnotation = "ako.vmware.com/controller-cluster-uuid" - TenantAnnotation = "ako.vmware.com/tenant-name" + VSAnnotation = "ako.vmware.com/host-fqdn-vs-uuid-map" + ControllerAnnotation = "ako.vmware.com/controller-cluster-uuid" + TenantAnnotation = "ako.vmware.com/tenant-name" + PassthroughAnnotation = "passthrough.ako.vmware.com/enabled" ) diff --git a/gslb/k8sobjects/ingress_object.go b/gslb/k8sobjects/ingress_object.go index d05e5b2b..d2fdbc63 100644 --- a/gslb/k8sobjects/ingress_object.go +++ b/gslb/k8sobjects/ingress_object.go @@ -19,6 +19,7 @@ import ( "errors" "fmt" "sort" + "strings" "sync" networkingv1 "k8s.io/api/networking/v1" @@ -152,6 +153,12 @@ func GetIngressHostMeta(ingress *networkingv1.Ingress, cname string) []IngressHo gslbutils.Logf("cluster: %s, ns: %s, ingress: %s, msg: skipping ingress because controller UUID absent in annotations", cname, ingress.Namespace, ingress.Name) } + passThroughEnabled := false + if gslbutils.GetCustomFqdnMode() { + if val, found := ingress.Annotations[gslbutils.PassthroughAnnotation]; found { + passThroughEnabled = strings.EqualFold(val, "true") + } + } for _, hip := range hostIPList { vsUUID, ok := vsUUIDs[hip.Hostname] if !ok && !syncVIPsOnly { @@ -169,6 +176,7 @@ func GetIngressHostMeta(ingress *networkingv1.Ingress, cname string) []IngressHo VirtualServiceUUID: vsUUID, ControllerUUID: controllerUUID, Tenant: tenant, + Passthrough: passThroughEnabled, } metaObj.Paths = make([]string, 0) metaObj.Labels = make(map[string]string) @@ -201,6 +209,7 @@ type IngressHostMeta struct { Paths []string TLS bool Tenant string + Passthrough bool } func (ing IngressHostMeta) GetType() string { @@ -257,7 +266,7 @@ func (ing IngressHostMeta) GetTLS() (bool, error) { } func (ing IngressHostMeta) IsPassthrough() bool { - return false + return ing.Passthrough } func (ing IngressHostMeta) GetVirtualServiceUUID() string { @@ -293,7 +302,7 @@ func (ing IngressHostMeta) GetIngressHostCksum() uint32 { cksum += utils.Hash(ing.Cluster) + utils.Hash(ing.Namespace) + utils.Hash(ing.IngName) + utils.Hash(ing.Hostname) + utils.Hash(ing.IPAddr) + utils.Hash(utils.Stringify(paths)) + - utils.Hash(ing.VirtualServiceUUID) + utils.Hash(ing.ControllerUUID) + utils.Hash(ing.Tenant) + utils.Hash(ing.VirtualServiceUUID) + utils.Hash(ing.ControllerUUID) + utils.Hash(ing.Tenant) + utils.Hash(utils.Stringify(ing.Passthrough)) return cksum } @@ -331,6 +340,11 @@ func (ihm IngressHostMeta) ApplyFilter() bool { selectedByGDP := ihm.ApplyGDPSelector() if selectedByGDP { if gslbutils.GetCustomFqdnMode() { + if ihm.IsPassthrough() { + gslbutils.Logf("cluster: %s, ns: %s, ingress host: %s, msg: passthrough ingress not supported in customfqdn mode", + ihm.Cluster, ihm.Namespace, ihm.Hostname) + return false + } _, err := fqdnMap.GetGlobalFqdnForLocalFqdn(ihm.Cluster, ihm.Hostname) if err != nil { gslbutils.Debugf("cluster: %s, ns: %s, ingress host: %s, msg: error in fetching global fqdn: %v", diff --git a/gslb/k8sobjects/route_object.go b/gslb/k8sobjects/route_object.go index 6eb8dd49..7b3a9983 100644 --- a/gslb/k8sobjects/route_object.go +++ b/gslb/k8sobjects/route_object.go @@ -284,6 +284,11 @@ func (route RouteMeta) ApplyFilter() bool { selectedByGDP := route.ApplyGDPSelector() if selectedByGDP { if gslbutils.GetCustomFqdnMode() { + if route.IsPassthrough() { + gslbutils.Logf("cluster: %s, ns: %s, route host: %s, msg: passthrough route not supported in customfqdn mode", + route.Cluster, route.Namespace, route.Hostname) + return false + } _, err := fqdnMap.GetGlobalFqdnForLocalFqdn(route.Cluster, route.Hostname) if err != nil { gslbutils.Debugf("cluster: %s, ns: %s, route host: %s, msg: error in fetching global fqdn: %v", diff --git a/gslb/test/integration/custom_fqdn/hostrule_test.go b/gslb/test/integration/custom_fqdn/hostrule_test.go index 1bea4417..df3b813a 100644 --- a/gslb/test/integration/custom_fqdn/hostrule_test.go +++ b/gslb/test/integration/custom_fqdn/hostrule_test.go @@ -234,6 +234,49 @@ func TestHRCreateUnsetIncludeAliases(t *testing.T) { }, 5*time.Second, 1*time.Second).Should(gomega.Equal(true)) } +// Update ingress,route to passthrough +func TestHRCreatePassThroughRouteAndIngress(t *testing.T) { + g := gomega.NewGomegaWithT(t) + ingObj, routeObj := Initialize(t, "hr-", hmRefs) + + // create a host rule for the ingress object's hostname with includeAliases = false, verify GS member + k8sHr := getHostRuleWithAliasesForCustomFqdn(hrNameK8s, ingCluster, ingObj.Namespace, ingObj.Spec.Rules[0].Host, gfqdn, + gslbutils.HostRuleAccepted, nil, false) + createHostRule(t, K8s, k8sHr) + + defaultDomainNames := []string{gfqdn} + expectedMembers = append(expectedMembers, getTestGSMemberFromIng(t, ingObj, ingCluster, 1)) + g.Eventually(func() bool { + return verifyGSMembers(t, expectedMembers, gfqdn, tenant, hmRefs, nil, nil, defaultDomainNames) + }, 5*time.Second, 1*time.Second).Should(gomega.Equal(true)) + + // create a host rule for the route object's hostname with includeAliases = false, verify GS members + ocHr := getHostRuleWithAliasesForCustomFqdn(hrNameOC, routeCluster, routeObj.Namespace, routeObj.Spec.Host, gfqdn, + gslbutils.HostRuleAccepted, nil, false) + createHostRule(t, Oshift, ocHr) + + expectedMembers = append(expectedMembers, getTestGSMemberFromRoute(t, routeObj, routeCluster, 1)) + g.Eventually(func() bool { + return verifyGSMembers(t, expectedMembers, gfqdn, tenant, hmRefs, nil, nil, defaultDomainNames) + }, 5*time.Second, 1*time.Second).Should(gomega.Equal(true)) + + // Update Ingress to Passthrough + ingObj.Annotations[gslbutils.PassthroughAnnotation] = "true" + k8sUpdateIngress(t, clusterClients[K8s], ingObj) + g.Eventually(func() bool { + return verifyGSMembers(t, []nodes.AviGSK8sObj{expectedMembers[1]}, gfqdn, tenant, hmRefs, nil, nil, defaultDomainNames) + }, 5*time.Second, 1*time.Second).Should(gomega.Equal(true)) + + //Update Route To Passthrough + routeObj.Spec.TLS = &routev1.TLSConfig{ + Termination: routev1.TLSTerminationPassthrough, + } + oshiftUpdateRoute(t, routeObj) + g.Eventually(func() bool { + return verifyGSDoesNotExist(t, gfqdn, tenant) + }, 5*time.Second, 1*time.Second).Should(gomega.Equal(true)) +} + // Create host rules and remove all aliases func TestHRRemoveAliases(t *testing.T) { g := gomega.NewGomegaWithT(t) diff --git a/gslb/test/integration/custom_fqdn/lib.go b/gslb/test/integration/custom_fqdn/lib.go index 8e6868f5..63260e2e 100644 --- a/gslb/test/integration/custom_fqdn/lib.go +++ b/gslb/test/integration/custom_fqdn/lib.go @@ -225,6 +225,13 @@ func k8sAddIngress(t *testing.T, kc *kubernetes.Clientset, name, ns, svc, cname return ingObj } +func k8sUpdateIngress(t *testing.T, kc *kubernetes.Clientset, ingObj *networkingv1.Ingress) { + _, err := kc.NetworkingV1().Ingresses(ingObj.Namespace).Update(context.TODO(), ingObj, metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("failed to update ingress: %v\n", err) + } +} + func oshiftAddRoute(t *testing.T, kc *kubernetes.Clientset, name, ns, svc, cname, host, ip string, tls bool) *routev1.Route { routeObj := BuildRouteObj(name, ns, svc, cname, host, ip, true) @@ -258,6 +265,12 @@ func oshiftAddRoute(t *testing.T, kc *kubernetes.Clientset, name, ns, svc, cname return newObj } +func oshiftUpdateRoute(t *testing.T, route *routev1.Route) { + _, err := oshiftClient.RouteV1().Routes(route.Namespace).Update(context.TODO(), route, metav1.UpdateOptions{}) + if err != nil { + t.Fatalf("Couldn't update route %v", err) + } +} func k8sDeleteIngress(t *testing.T, kc *kubernetes.Clientset, name string, ns string) { err := kc.NetworkingV1().Ingresses(ns).Delete(context.TODO(), name, metav1.DeleteOptions{}) if err != nil {