Skip to content
This repository has been archived by the owner on Oct 7, 2020. It is now read-only.

add test for manager. #399

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ require (
github.com/kylelemons/godebug v1.1.0
github.com/mholt/archiver v3.1.1+incompatible
github.com/nwaples/rardecode v1.0.0 // indirect
github.com/onsi/gomega v1.5.0
github.com/openshift/api v3.9.1-0.20191008181517-e4fd21196097+incompatible // indirect
github.com/openshift/cluster-network-operator v0.0.0-20191009144453-fdceef8e1a7b
github.com/pierrec/lz4 v2.2.5+incompatible // indirect
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
// Copyright 2019 Istio Authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package istiocontrolplane

import (
"os"
"path/filepath"
"sync"
"testing"

"github.com/onsi/gomega"
"k8s.io/client-go/kubernetes/scheme"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/envtest"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/reconcile"

"istio.io/operator/pkg/apis"
"istio.io/pkg/log"
)

var cfg *rest.Config

func TestMain(m *testing.M) {
t := &envtest.Environment{
CRDDirectoryPaths: []string{
filepath.Join("..", "..", "..", "deploy", "crds"),
},
}

apis.AddToScheme(scheme.Scheme)

var err error
if cfg, err = t.Start(); err != nil {
log.Fatalf("error to start the test env: %s", err)
}

code := m.Run()

t.Stop()
os.Exit(code)
}

// SetupTestReconcile returns a reconcile.Reconcile implementation that delegates to inner and
// writes the request to requests after Reconcile is finished.
func SetupTestReconcile(inner reconcile.Reconciler) (reconcile.Reconciler, chan reconcile.Request) {
requests := make(chan reconcile.Request)
fn := reconcile.Func(func(req reconcile.Request) (reconcile.Result, error) {
result, err := inner.Reconcile(req)
requests <- req
return result, err
})

return fn, requests
}

// StartTestManager adds recFn
func StartTestManager(mgr manager.Manager, g *gomega.GomegaWithT) (chan struct{}, *sync.WaitGroup) {
stop := make(chan struct{})
wg := &sync.WaitGroup{}
wg.Add(1)

go func() {
defer wg.Done()
g.Expect(mgr.Start(stop)).NotTo(gomega.HaveOccurred())
}()

return stop, wg
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import (
"fmt"
"strconv"
"testing"
"time"

"github.com/onsi/gomega"

"istio.io/operator/pkg/apis/istio/v1alpha2"
"istio.io/operator/pkg/helmreconciler"
Expand All @@ -29,10 +32,26 @@ import (
"k8s.io/client-go/kubernetes/scheme"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/fake"
"sigs.k8s.io/controller-runtime/pkg/manager"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
)

const (
timeout = time.Second * 2
defaultProfile = "default"
demoProfile = "demo"
minimalProfile = "minimal"
sdsProfile = "sds"
)

var (
c client.Client
icpkey = types.NamespacedName{
Name: "test-istiocontrolplane",
Namespace: "test-istio-operator",
}
expectedRequest = reconcile.Request{NamespacedName: icpkey}

minimalStatus = map[string]*v1alpha2.InstallStatus_VersionStatus{
"Pilot": {
Status: v1alpha2.InstallStatus_HEALTHY,
Expand Down Expand Up @@ -156,28 +175,28 @@ func TestICPController_SwitchProfile(t *testing.T) {
cases := []testCase{
{
description: "switch profile from minimal to default",
initialProfile: "minimal",
targetProfile: "default",
initialProfile: minimalProfile,
targetProfile: defaultProfile,
},
{
description: "switch profile from default to minimal",
initialProfile: "default",
targetProfile: "minimal",
initialProfile: defaultProfile,
targetProfile: minimalProfile,
},
{
description: "switch profile from default to demo",
initialProfile: "default",
targetProfile: "demo",
initialProfile: defaultProfile,
targetProfile: demoProfile,
},
{
description: "switch profile from demo to sds",
initialProfile: "demo",
targetProfile: "sds",
initialProfile: demoProfile,
targetProfile: sdsProfile,
},
{
description: "switch profile from sds to default",
initialProfile: "sds",
targetProfile: "default",
initialProfile: sdsProfile,
targetProfile: defaultProfile,
},
}
for i, c := range cases {
Expand All @@ -186,16 +205,15 @@ func TestICPController_SwitchProfile(t *testing.T) {
})
}
}

func testSwitchProfile(t *testing.T, c testCase) {
t.Helper()
name := "example-istiocontrolplane"
namespace := "istio-system"
icp := &v1alpha2.IstioControlPlane{
Kind: "IstioControlPlane",
ApiVersion: "install.istio.io/v1alpha2",
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Name: icpkey.Name,
Namespace: icpkey.Namespace,
},
Spec: &v1alpha2.IstioControlPlaneSpec{
Profile: c.initialProfile,
Expand All @@ -213,8 +231,8 @@ func testSwitchProfile(t *testing.T, c testCase) {

req := reconcile.Request{
NamespacedName: types.NamespacedName{
Name: name,
Namespace: namespace,
Name: icpkey.Name,
Namespace: icpkey.Namespace,
},
}
res, err := r.Reconcile(req)
Expand Down Expand Up @@ -272,13 +290,13 @@ func checkICPStatus(cl client.Client, key client.ObjectKey, profile string) (boo
}
var status map[string]*v1alpha2.InstallStatus_VersionStatus
switch profile {
case "minimal":
case minimalProfile:
status = minimalStatus
case "default":
case defaultProfile:
status = defaultStatus
case "sds":
case sdsProfile:
status = sdsStatus
case "demo":
case demoProfile:
status = demoStatus
}
installStatus := instance.GetStatus()
Expand All @@ -298,3 +316,45 @@ func checkICPStatus(cl client.Client, key client.ObjectKey, profile string) (boo
}
return true, nil
}

// TestReconcile test the reconciler process with manager from end to end.
func TestReconcile(t *testing.T) {
g := gomega.NewGomegaWithT(t)

// Setup the Manager and Controller. Wrap the Controller Reconcile function so it writes each request to a
// channel when it is finished.
mgr, err := manager.New(cfg, manager.Options{})
g.Expect(err).NotTo(gomega.HaveOccurred())

c = mgr.GetClient()

rec := newReconciler(mgr)
recFn, requests := SetupTestReconcile(rec)

g.Expect(add(mgr, recFn)).NotTo(gomega.HaveOccurred())

stopMgr, mgrStopped := StartTestManager(mgr, g)

defer func() {
close(stopMgr)
mgrStopped.Wait()
}()

icp := &v1alpha2.IstioControlPlane{
Kind: "IstioControlPlane",
ApiVersion: "install.istio.io/v1alpha2",
ObjectMeta: metav1.ObjectMeta{
Name: icpkey.Name,
Namespace: icpkey.Namespace,
},
Spec: &v1alpha2.IstioControlPlaneSpec{
Profile: defaultProfile,
},
}

g.Expect(c.Create(context.TODO(), icp)).NotTo(gomega.HaveOccurred())

defer c.Delete(context.TODO(), icp)

g.Eventually(requests, timeout).Should(gomega.Receive(gomega.Equal(expectedRequest)))
}