github.com/solo-io/service-mesh-hub@v0.9.2/test/e2e/istio/failover_service_test.go (about) 1 package istio_test 2 3 import ( 4 "context" 5 "fmt" 6 7 . "github.com/onsi/ginkgo" 8 . "github.com/onsi/gomega" 9 networkingv1alpha2 "github.com/solo-io/service-mesh-hub/pkg/api/networking.smh.solo.io/v1alpha2" 10 "github.com/solo-io/service-mesh-hub/test/e2e" 11 "github.com/solo-io/service-mesh-hub/test/utils" 12 v1 "github.com/solo-io/skv2/pkg/api/core.skv2.solo.io/v1" 13 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 14 ) 15 16 var _ = Describe("FailoverService", func() { 17 var ( 18 err error 19 manifest utils.Manifest 20 ctx = context.Background() 21 failoverServiceObjMeta = metav1.ObjectMeta{ 22 Name: "reviews-failover", 23 Namespace: BookinfoNamespace, 24 } 25 ) 26 27 AfterEach(func() { 28 manifest.Cleanup(BookinfoNamespace) 29 // Ensure restoring bookinfo containers if test fails. 30 env := e2e.GetEnv() 31 env.Management.EnableContainer(ctx, BookinfoNamespace, "reviews-v1") 32 env.Management.EnableContainer(ctx, BookinfoNamespace, "reviews-v2") 33 env.Management.WaitForRollout(ctx, BookinfoNamespace, "reviews-v1") 34 env.Management.WaitForRollout(ctx, BookinfoNamespace, "reviews-v2") 35 }) 36 37 It("should create a failover service", func() { 38 manifest, err = utils.NewManifest("failover_service_test_manifest.yaml") 39 Expect(err).ToNot(HaveOccurred()) 40 env := e2e.GetEnv() 41 42 failoverServiceHostname := "reviews-failover.bookinfo.global" 43 curlFailoverService := func() string { 44 return curlFromProductpage(fmt.Sprintf("http://%s:9080/reviews/1", failoverServiceHostname)) 45 } 46 47 By("creating a new FailoverService with the prerequisite TrafficPolicy and VirtualMesh", func() { 48 trafficPolicy := &networkingv1alpha2.TrafficPolicy{ 49 TypeMeta: metav1.TypeMeta{ 50 Kind: "TrafficPolicy", 51 APIVersion: networkingv1alpha2.SchemeGroupVersion.String(), 52 }, 53 ObjectMeta: metav1.ObjectMeta{ 54 Name: "reviews-outlier-detection", 55 Namespace: BookinfoNamespace, 56 }, 57 Spec: networkingv1alpha2.TrafficPolicySpec{ 58 DestinationSelector: []*networkingv1alpha2.TrafficTargetSelector{ 59 { 60 KubeServiceRefs: &networkingv1alpha2.TrafficTargetSelector_KubeServiceRefs{ 61 Services: []*v1.ClusterObjectRef{ 62 { 63 Name: "reviews", 64 Namespace: BookinfoNamespace, 65 ClusterName: mgmtClusterName, 66 }, 67 { 68 Name: "reviews", 69 Namespace: BookinfoNamespace, 70 ClusterName: remoteClusterName, 71 }, 72 }, 73 }, 74 }, 75 }, 76 OutlierDetection: &networkingv1alpha2.TrafficPolicySpec_OutlierDetection{ 77 ConsecutiveErrors: 1, 78 }, 79 }, 80 } 81 failoverService := &networkingv1alpha2.FailoverService{ 82 TypeMeta: metav1.TypeMeta{ 83 Kind: "FailoverService", 84 APIVersion: networkingv1alpha2.SchemeGroupVersion.String(), 85 }, 86 ObjectMeta: failoverServiceObjMeta, 87 Spec: networkingv1alpha2.FailoverServiceSpec{ 88 Hostname: failoverServiceHostname, 89 Port: &networkingv1alpha2.FailoverServiceSpec_Port{ 90 Number: 9080, 91 Protocol: "http", 92 }, 93 Meshes: []*v1.ObjectRef{ 94 masterMesh, 95 }, 96 BackingServices: []*networkingv1alpha2.FailoverServiceSpec_BackingService{ 97 { 98 BackingServiceType: &networkingv1alpha2.FailoverServiceSpec_BackingService_KubeService{ 99 KubeService: &v1.ClusterObjectRef{ 100 Name: "reviews", 101 Namespace: BookinfoNamespace, 102 ClusterName: mgmtClusterName, 103 }, 104 }, 105 }, 106 { 107 BackingServiceType: &networkingv1alpha2.FailoverServiceSpec_BackingService_KubeService{ 108 KubeService: &v1.ClusterObjectRef{ 109 Name: "reviews", 110 Namespace: BookinfoNamespace, 111 ClusterName: remoteClusterName, 112 }, 113 }, 114 }, 115 }, 116 }, 117 } 118 119 err := manifest.AppendResources(trafficPolicy) 120 Expect(err).NotTo(HaveOccurred()) 121 err = manifest.KubeApply(BookinfoNamespace) 122 Expect(err).NotTo(HaveOccurred()) 123 // Wait for TrafficPolicy with outlier detection to be processed before creating FailoverService. 124 utils.AssertTrafficPolicyStatuses(dynamicClient, BookinfoNamespace) 125 126 err = manifest.AppendResources(failoverService) 127 Expect(err).NotTo(HaveOccurred()) 128 err = manifest.KubeApply(BookinfoNamespace) 129 Expect(err).NotTo(HaveOccurred()) 130 131 // Make it failover to remote cluster with reviews-v3, disable all master cluster reviews pods to prove 132 // that request is being served by remote cluster 133 env.Management.DisableContainer(ctx, BookinfoNamespace, "reviews-v1", "reviews") 134 env.Management.DisableContainer(ctx, BookinfoNamespace, "reviews-v2", "reviews") 135 env.Management.WaitForRollout(ctx, BookinfoNamespace, "reviews-v1") 136 env.Management.WaitForRollout(ctx, BookinfoNamespace, "reviews-v2") 137 138 // first check that we have a response to reduce flakiness 139 Eventually(curlFailoverService, "1m", "1s").Should(ContainSubstring("200 OK")) 140 }) 141 142 By("setting a TrafficShift to redirect traffic to the FailoverService", func() { 143 trafficPolicy := &networkingv1alpha2.TrafficPolicy{ 144 TypeMeta: metav1.TypeMeta{ 145 Kind: "TrafficPolicy", 146 APIVersion: networkingv1alpha2.SchemeGroupVersion.String(), 147 }, 148 ObjectMeta: metav1.ObjectMeta{ 149 Name: "reviews-shift-failover", 150 Namespace: BookinfoNamespace, 151 }, 152 Spec: networkingv1alpha2.TrafficPolicySpec{ 153 DestinationSelector: []*networkingv1alpha2.TrafficTargetSelector{ 154 { 155 KubeServiceRefs: &networkingv1alpha2.TrafficTargetSelector_KubeServiceRefs{ 156 Services: []*v1.ClusterObjectRef{ 157 { 158 Name: "reviews", 159 Namespace: BookinfoNamespace, 160 ClusterName: mgmtClusterName, 161 }, 162 }, 163 }, 164 }, 165 }, 166 TrafficShift: &networkingv1alpha2.TrafficPolicySpec_MultiDestination{ 167 Destinations: []*networkingv1alpha2.TrafficPolicySpec_MultiDestination_WeightedDestination{ 168 { 169 DestinationType: &networkingv1alpha2.TrafficPolicySpec_MultiDestination_WeightedDestination_FailoverService{ 170 FailoverService: &networkingv1alpha2.TrafficPolicySpec_MultiDestination_WeightedDestination_FailoverServiceDestination{ 171 Name: failoverServiceObjMeta.Name, 172 Namespace: failoverServiceObjMeta.Namespace, 173 }, 174 }, 175 }, 176 }, 177 }, 178 }, 179 } 180 err := manifest.AppendResources(trafficPolicy) 181 Expect(err).NotTo(HaveOccurred()) 182 err = manifest.KubeApply(BookinfoNamespace) 183 Expect(err).NotTo(HaveOccurred()) 184 utils.AssertTrafficPolicyStatuses(dynamicClient, BookinfoNamespace) 185 186 // reviews-v3 is only deployed on remote cluster, so receiving a response proves that the FailoverService is working 187 Eventually(curlReviews, "1m", "1s").Should(ContainSubstring(`"color": "red"`)) 188 }) 189 190 By("re-enable management-plane reviews deployments", func() { 191 err := manifest.KubeDelete(BookinfoNamespace) 192 Expect(err).NotTo(HaveOccurred()) 193 194 env.Management.EnableContainer(ctx, BookinfoNamespace, "reviews-v1") 195 env.Management.EnableContainer(ctx, BookinfoNamespace, "reviews-v2") 196 env.Management.WaitForRollout(ctx, BookinfoNamespace, "reviews-v1") 197 env.Management.WaitForRollout(ctx, BookinfoNamespace, "reviews-v2") 198 Eventually(curlReviews, "1m", "1s").Should(ContainSubstring("200 OK")) 199 }) 200 }) 201 })