Skip to content

Commit

Permalink
Adding more unit tests (#89)
Browse files Browse the repository at this point in the history
* Added tests for destination rule creation

Signed-off-by: Joe Peacock <joe_peacock@intuit.com>

* Uncommented/fixed a bunch of SE tests

Signed-off-by: Joe Peacock <joe_peacock@intuit.com>

* Uncommented/fixed more se tests

Signed-off-by: Joe Peacock <joe_peacock@intuit.com>

Co-authored-by: Joe Peacock <joe_peacock@intuit.com>
Signed-off-by: Madeline <madeline_li@intuit.com>
  • Loading branch information
2 people authored and Mengying-intuit committed Apr 20, 2020
1 parent 30b245c commit a5f69b1
Show file tree
Hide file tree
Showing 7 changed files with 691 additions and 343 deletions.
14 changes: 9 additions & 5 deletions admiral/pkg/clusters/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -409,7 +409,7 @@ func createDestinationRuleForLocal(remoteController *RemoteController, localDrNa
}
}

func handleVirtualServiceEvent(obj *v1alpha3.VirtualService, vh *VirtualServiceHandler, event common.Event, resourceType common.ResourceType) {
func handleVirtualServiceEvent(obj *v1alpha3.VirtualService, vh *VirtualServiceHandler, event common.Event, resourceType common.ResourceType) error {

log.Infof(LogFormat, "Event", resourceType, obj.Name, vh.ClusterID, "Received event")

Expand All @@ -423,19 +423,19 @@ func handleVirtualServiceEvent(obj *v1alpha3.VirtualService, vh *VirtualServiceH

if obj.Namespace == syncNamespace {
log.Infof(LogFormat, "Event", resourceType, obj.Name, clusterId, "Skipping the namespace: "+obj.Namespace)
return
return nil
}

if len(virtualService.Hosts) > 1 {
log.Errorf(LogFormat, "Event", resourceType, obj.Name, clusterId, "Skipping as multiple hosts not supported for virtual service namespace="+obj.Namespace)
return
return nil
}

dependentClusters := r.AdmiralCache.CnameDependentClusterCache.Get(virtualService.Hosts[0])

if dependentClusters == nil {
log.Infof(LogFormat, "Event", resourceType, obj.Name, clusterId, "No dependent clusters found")
return
return nil
}

log.Infof(LogFormat, "Event", "VirtualService", obj.Name, clusterId, "Processing")
Expand All @@ -448,7 +448,10 @@ func handleVirtualServiceEvent(obj *v1alpha3.VirtualService, vh *VirtualServiceH

if event == common.Delete {
log.Infof(LogFormat, "Delete", "VirtualService", obj.Name, clusterId, "Success")
rc.VirtualServiceController.IstioClient.NetworkingV1alpha3().VirtualServices(syncNamespace).Delete(obj.Name, &v12.DeleteOptions{})
err := rc.VirtualServiceController.IstioClient.NetworkingV1alpha3().VirtualServices(syncNamespace).Delete(obj.Name, &v12.DeleteOptions{})
if err != nil {
return err
}

} else {

Expand All @@ -474,6 +477,7 @@ func handleVirtualServiceEvent(obj *v1alpha3.VirtualService, vh *VirtualServiceH
}

}
return nil
}

func addUpdateVirtualService(obj *v1alpha3.VirtualService, exist *v1alpha3.VirtualService, namespace string, rc *RemoteController) {
Expand Down
299 changes: 288 additions & 11 deletions admiral/pkg/clusters/handler_test.go
Original file line number Diff line number Diff line change
@@ -1,35 +1,46 @@
package clusters

import (
"github.com/gogo/protobuf/types"
"github.com/google/go-cmp/cmp"
"github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/model"
"github.com/istio-ecosystem/admiral/admiral/pkg/apis/admiral/v1"
"github.com/istio-ecosystem/admiral/admiral/pkg/controller/common"
"github.com/istio-ecosystem/admiral/admiral/pkg/controller/istio"
"istio.io/api/networking/v1alpha3"
v1alpha32 "istio.io/client-go/pkg/apis/networking/v1alpha3"
v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
"testing"

istiofake "istio.io/client-go/pkg/clientset/versioned/fake"
)

func TestIgnoreIstioResource(t *testing.T) {

//Struct of test case info. Name is required.
testCases := []struct {
name string
exportTo []string
name string
exportTo []string
expectedResult bool
}{
{
name: "Should return false when exportTo is not present",
exportTo: nil,
name: "Should return false when exportTo is not present",
exportTo: nil,
expectedResult: false,
},
{
name: "Should return false when its exported to *",
exportTo: []string {"*"},
name: "Should return false when its exported to *",
exportTo: []string{"*"},
expectedResult: false,
},
{
name: "Should return true when its exported to .",
exportTo: []string {"."},
name: "Should return true when its exported to .",
exportTo: []string{"."},
expectedResult: true,
},
{
name: "Should return true when its exported to a handful of namespaces",
exportTo: []string {"namespace1", "namespace2"},
name: "Should return true when its exported to a handful of namespaces",
exportTo: []string{"namespace1", "namespace2"},
expectedResult: true,
},
}
Expand All @@ -41,7 +52,273 @@ func TestIgnoreIstioResource(t *testing.T) {
if result == c.expectedResult {
//perfect
} else {
t.Errorf("Failed. Got %v, expected %v",result, c.expectedResult)
t.Errorf("Failed. Got %v, expected %v", result, c.expectedResult)
}
})
}
}

func TestGetDestinationRule(t *testing.T) {
//Do setup here
mTLS := &v1alpha3.TrafficPolicy{Tls: &v1alpha3.TLSSettings{Mode: v1alpha3.TLSSettings_ISTIO_MUTUAL}}

noGtpDr := v1alpha3.DestinationRule{
Host: "qa.myservice.global",
TrafficPolicy: mTLS,
}

basicGtpDr := v1alpha3.DestinationRule{
Host: "qa.myservice.global",
TrafficPolicy: &v1alpha3.TrafficPolicy{
Tls: &v1alpha3.TLSSettings{Mode: v1alpha3.TLSSettings_ISTIO_MUTUAL},
LoadBalancer: &v1alpha3.LoadBalancerSettings{
LbPolicy: &v1alpha3.LoadBalancerSettings_Simple{Simple: v1alpha3.LoadBalancerSettings_ROUND_ROBIN},
LocalityLbSetting: &v1alpha3.LocalityLoadBalancerSetting{},
},
OutlierDetection: &v1alpha3.OutlierDetection{
BaseEjectionTime: &types.Duration{Seconds: 120},
ConsecutiveErrors: 10,
Interval: &types.Duration{Seconds: 60},
},
},
}

failoverGtpDr := v1alpha3.DestinationRule{
Host: "qa.myservice.global",
TrafficPolicy: &v1alpha3.TrafficPolicy{
Tls: &v1alpha3.TLSSettings{Mode: v1alpha3.TLSSettings_ISTIO_MUTUAL},
LoadBalancer: &v1alpha3.LoadBalancerSettings{
LbPolicy: &v1alpha3.LoadBalancerSettings_Simple{Simple: v1alpha3.LoadBalancerSettings_ROUND_ROBIN},
LocalityLbSetting: &v1alpha3.LocalityLoadBalancerSetting{
Distribute: []*v1alpha3.LocalityLoadBalancerSetting_Distribute{
{
From: "uswest2/*",
To: map[string]uint32{"us-west-2": 100},
},
},
},
},
OutlierDetection: &v1alpha3.OutlierDetection{
BaseEjectionTime: &types.Duration{Seconds: 120},
ConsecutiveErrors: 10,
Interval: &types.Duration{Seconds: 60},
},
},
}

topologyGTPBody := model.GlobalTrafficPolicy{
Policy: []*model.TrafficPolicy{
{
LbType: model.TrafficPolicy_TOPOLOGY,
Target: []*model.TrafficGroup{
{
Region: "us-west-2",
Weight: 100,
},
},
},
},
}

topologyGTP := v1.GlobalTrafficPolicy{
Spec: topologyGTPBody,
}
topologyGTP.Name = "myGTP"
topologyGTP.Namespace = "myNS"

failoverGTPBody := model.GlobalTrafficPolicy{
Policy: []*model.TrafficPolicy{
{
LbType: model.TrafficPolicy_FAILOVER,
Target: []*model.TrafficGroup{
{
Region: "us-west-2",
Weight: 100,
},
},
},
},
}

failoverGTP := v1.GlobalTrafficPolicy{
Spec: failoverGTPBody,
}
failoverGTP.Name = "myGTP"
failoverGTP.Namespace = "myNS"

//Struct of test case info. Name is required.
testCases := []struct {
name string
host string
locality string
gtp *v1.GlobalTrafficPolicy
destinationRule *v1alpha3.DestinationRule
}{
{
name: "Should handle a nil GTP",
host: "qa.myservice.global",
locality: "uswest2",
gtp: nil,
destinationRule: &noGtpDr,
},
{
name: "Should handle a topology GTP",
host: "qa.myservice.global",
locality: "uswest2",
gtp: &topologyGTP,
destinationRule: &basicGtpDr,
},
{
name: "Should handle a failover GTP",
host: "qa.myservice.global",
locality: "uswest2",
gtp: &failoverGTP,
destinationRule: &failoverGtpDr,
},
}

//Run the test for every provided case
for _, c := range testCases {
t.Run(c.name, func(t *testing.T) {
result := getDestinationRule(c.host, c.locality, c.gtp)
if !cmp.Equal(result, c.destinationRule) {
t.Fatalf("DestinationRule Mismatch. Diff: %v", cmp.Diff(result, c.destinationRule))
}
})
}
}


func TestHandleVirtualServiceEvent(t *testing.T) {
//Do setup here
syncNs := v1alpha32.VirtualService{}
syncNs.Namespace = "ns"

tooManyHosts := v1alpha32.VirtualService{
Spec: v1alpha3.VirtualService{
Hosts: []string{"qa.blah.global", "e2e.blah.global"},
},
}
tooManyHosts.Namespace = "other-ns"

happyPath := v1alpha32.VirtualService{
Spec: v1alpha3.VirtualService{
Hosts: []string{"e2e.blah.global"},
},
}
happyPath.Namespace = "other-ns"
happyPath.Name = "vs-name"

cnameCache := common.NewMapOfMaps()
noDependencClustersHandler := VirtualServiceHandler{
RemoteRegistry: &RemoteRegistry{
remoteControllers: map[string]*RemoteController{},
AdmiralCache: &AdmiralCache{
CnameDependentClusterCache: cnameCache,
},
},
}

fakeIstioClient := istiofake.NewSimpleClientset()
goodCnameCache := common.NewMapOfMaps()
goodCnameCache.Put("e2e.blah.global", "cluster.k8s.global", "cluster.k8s.global")
handlerEmptyClient := VirtualServiceHandler{
RemoteRegistry: &RemoteRegistry{
remoteControllers: map[string]*RemoteController{
"cluster.k8s.global": &RemoteController{
VirtualServiceController: &istio.VirtualServiceController{
IstioClient: fakeIstioClient,
},
},
},
AdmiralCache: &AdmiralCache{
CnameDependentClusterCache: goodCnameCache,
},
},
}

fullFakeIstioClient := istiofake.NewSimpleClientset()
fullFakeIstioClient.NetworkingV1alpha3().VirtualServices("ns").Create(&v1alpha32.VirtualService{
ObjectMeta: v12.ObjectMeta{
Name: "vs-name",
},
Spec: v1alpha3.VirtualService{
Hosts: []string{"e2e.blah.global"},
},
})
handlerFullClient := VirtualServiceHandler{
RemoteRegistry: &RemoteRegistry{
remoteControllers: map[string]*RemoteController{
"cluster.k8s.global": &RemoteController{
VirtualServiceController: &istio.VirtualServiceController{
IstioClient: fullFakeIstioClient,
},
},
},
AdmiralCache: &AdmiralCache{
CnameDependentClusterCache: goodCnameCache,
},
},
}

//Struct of test case info. Name is required.
testCases := []struct {
name string
vs *v1alpha32.VirtualService
handler *VirtualServiceHandler
expectedError error
event common.Event
}{
{
name: "Virtual Service in sync namespace",
vs: &syncNs,
expectedError: nil,
handler: &noDependencClustersHandler,
event: 0,
},
{
name: "Virtual Service with multiple hosts",
vs: &tooManyHosts,
expectedError: nil,
handler: &noDependencClustersHandler,
event: 0,
},
{
name: "No dependent clusters",
vs: &happyPath,
expectedError: nil,
handler: &noDependencClustersHandler,
event: 0,
},
{
name: "New Virtual Service",
vs: &happyPath,
expectedError: nil,
handler: &handlerEmptyClient,
event: 0,
},
{
name: "Existing Virtual Service",
vs: &happyPath,
expectedError: nil,
handler: &handlerFullClient,
event: 1,
},
{
name: "Deleted Virtual Service",
vs: &happyPath,
expectedError: nil,
handler: &handlerFullClient,
event: 2,
},
}

//Run the test for every provided case
for _, c := range testCases {
t.Run(c.name, func(t *testing.T) {
err := handleVirtualServiceEvent(c.vs, c.handler, c.event, common.VirtualService)
if err != c.expectedError {
t.Fatalf("Error mismatch, expected %v but got %v", c.expectedError, err)
}
})
}
Expand Down
Loading

0 comments on commit a5f69b1

Please sign in to comment.