Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adding more unit tests #89

Merged
merged 5 commits into from
Apr 1, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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