Skip to content

Commit

Permalink
Add scaffolding for supporting additional whitebox testing
Browse files Browse the repository at this point in the history
  • Loading branch information
rramkumar1 committed Jan 15, 2019
1 parent 99946cd commit 56f650a
Show file tree
Hide file tree
Showing 10 changed files with 209 additions and 43 deletions.
19 changes: 2 additions & 17 deletions cmd/e2e-test/basic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (
"context"
"testing"

"github.com/kr/pretty"
"k8s.io/api/extensions/v1beta1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-gce/pkg/e2e"
Expand All @@ -36,34 +35,25 @@ func TestBasic(t *testing.T) {
for _, tc := range []struct {
desc string
ing *v1beta1.Ingress

numForwardingRules int
numBackendServices int
}{
{
desc: "http default backend",
ing: fuzz.NewIngressBuilder("", "ingress-1", "").
DefaultBackend("service-1", port80).
Build(),
numForwardingRules: 1,
numBackendServices: 1,
},
{
desc: "http one path",
ing: fuzz.NewIngressBuilder("", "ingress-1", "").
AddPath("test.com", "/", "service-1", port80).
Build(),
numForwardingRules: 1,
numBackendServices: 2,
},
{
desc: "http multiple paths",
ing: fuzz.NewIngressBuilder("", "ingress-1", "").
AddPath("test.com", "/foo", "service-1", port80).
AddPath("test.com", "/bar", "service-1", port80).
Build(),
numForwardingRules: 1,
numBackendServices: 2,
},
} {
tc := tc // Capture tc as we are running this in parallel.
Expand All @@ -89,7 +79,6 @@ func TestBasic(t *testing.T) {
}
t.Logf("GCLB resources createdd (%s/%s)", s.Namespace, tc.ing.Name)

// Perform whitebox testing.
if len(ing.Status.LoadBalancer.Ingress) < 1 {
t.Fatalf("Ingress does not have an IP: %+v", ing.Status)
}
Expand All @@ -101,12 +90,8 @@ func TestBasic(t *testing.T) {
t.Fatalf("Error getting GCP resources for LB with IP = %q: %v", vip, err)
}

// Do some cursory checks on the GCP objects.
if len(gclb.ForwardingRule) != tc.numForwardingRules {
t.Errorf("got %d fowarding rules, want %d;\n%s", len(gclb.ForwardingRule), tc.numForwardingRules, pretty.Sprint(gclb.ForwardingRule))
}
if len(gclb.BackendService) != tc.numBackendServices {
t.Errorf("got %d backend services, want %d;\n%s", len(gclb.BackendService), tc.numBackendServices, pretty.Sprint(gclb.BackendService))
if err := e2e.PerformWhiteboxTests(s, tc.ing, gclb); err != nil {
t.Fatalf("Error performing whitebox tests: %v", err)
}

deleteOptions := &fuzz.GCLBDeleteOptions{
Expand Down
14 changes: 0 additions & 14 deletions cmd/e2e-test/upgrade_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ import (
"strings"
"testing"

"github.com/kr/pretty"
"k8s.io/api/extensions/v1beta1"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/ingress-gce/pkg/e2e"
Expand All @@ -38,16 +37,12 @@ func TestUpgrade(t *testing.T) {
desc string
ing *v1beta1.Ingress

numForwardingRules int
numBackendServices int
}{
{
desc: "http default backend",
ing: fuzz.NewIngressBuilder("", "ingress-1", "").
DefaultBackend("service-1", port80).
Build(),
numForwardingRules: 1,
numBackendServices: 1,
},
} {
tc := tc // Capture tc as we are running this in parallel.
Expand Down Expand Up @@ -116,7 +111,6 @@ func TestUpgrade(t *testing.T) {
t.Logf("GCLB is stable (%s/%s)", s.Namespace, tc.ing.Name)
}

// Perform whitebox testing.
if len(ing.Status.LoadBalancer.Ingress) < 1 {
t.Fatalf("Ingress does not have an IP: %+v", ing.Status)
}
Expand All @@ -128,14 +122,6 @@ func TestUpgrade(t *testing.T) {
t.Fatalf("Error getting GCP resources for LB with IP = %q: %v", vip, err)
}

// Do some cursory checks on the GCP objects.
if len(gclb.ForwardingRule) != tc.numForwardingRules {
t.Errorf("got %d fowarding rules, want %d;\n%s", len(gclb.ForwardingRule), tc.numForwardingRules, pretty.Sprint(gclb.ForwardingRule))
}
if len(gclb.BackendService) != tc.numBackendServices {
t.Errorf("got %d backend services, want %d;\n%s", len(gclb.BackendService), tc.numBackendServices, pretty.Sprint(gclb.BackendService))
}

runs++

// If the Master has upgraded and the Ingress is stable,
Expand Down
7 changes: 6 additions & 1 deletion cmd/fuzzer/app/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import (
"k8s.io/ingress-gce/pkg/e2e"
"k8s.io/ingress-gce/pkg/fuzz"
"k8s.io/ingress-gce/pkg/fuzz/features"
"k8s.io/ingress-gce/pkg/fuzz/whitebox"

// Pull in the auth library for GCP.
_ "k8s.io/client-go/plugin/pkg/client/auth/gcp"
Expand Down Expand Up @@ -133,7 +134,7 @@ func Validate() {

fmt.Printf("Ingress =\n%s\n\n", pretty.Sprint(*ing))

iv, err := fuzz.NewIngressValidator(env, ing, fs, nil)
iv, err := fuzz.NewIngressValidator(env, ing, fs, whitebox.AllTests, nil)
if err != nil {
panic(err)
}
Expand All @@ -151,6 +152,10 @@ func Validate() {
panic(err)
}
fmt.Printf("GCP resources = \n%s\n", pretty.Sprint(gclb))

if err := iv.PerformWhiteboxTests(gclb); err != nil {
panic(err)
}
}

func homeDir() string {
Expand Down
12 changes: 11 additions & 1 deletion pkg/e2e/helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/ingress-gce/pkg/fuzz"
"k8s.io/ingress-gce/pkg/fuzz/features"
"k8s.io/ingress-gce/pkg/fuzz/whitebox"
"k8s.io/kubernetes/pkg/cloudprovider/providers/gce/cloud"
)

Expand All @@ -53,7 +54,7 @@ func WaitForIngress(s *Sandbox, ing *v1beta1.Ingress, options *WaitForIngressOpt
if err != nil {
return true, err
}
validator, err := fuzz.NewIngressValidator(s.ValidatorEnv, ing, features.All, nil)
validator, err := fuzz.NewIngressValidator(s.ValidatorEnv, ing, features.All, []fuzz.WhiteboxTest{}, nil)
if err != nil {
return true, err
}
Expand All @@ -70,6 +71,15 @@ func WaitForIngress(s *Sandbox, ing *v1beta1.Ingress, options *WaitForIngressOpt
return ing, err
}

// PerformWhiteboxTests runs the whitebox tests against the Ingress.
func PerformWhiteboxTests(s *Sandbox, ing *v1beta1.Ingress, gclb *fuzz.GCLB) error {
validator, err := fuzz.NewIngressValidator(s.ValidatorEnv, ing, []fuzz.Feature{}, whitebox.AllTests, nil)
if err != nil {
return err
}
return validator.PerformWhiteboxTests(gclb)
}

// WaitForIngressDeletion deletes the given ingress and waits for the
// resources associated with it to be deleted.
func WaitForIngressDeletion(ctx context.Context, g *fuzz.GCLB, s *Sandbox, ing *v1beta1.Ingress, options *fuzz.GCLBDeleteOptions) error {
Expand Down
26 changes: 19 additions & 7 deletions pkg/fuzz/validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ func defaultAttributes() *IngressValidatorAttributes {
// NewIngressValidator returns a new validator for checking the correctness of
// an Ingress spec against the behavior of the instantiated load balancer.
// If attribs is nil, then the default set of attributes will be used.
func NewIngressValidator(env ValidatorEnv, ing *v1beta1.Ingress, features []Feature, attribs *IngressValidatorAttributes) (*IngressValidator, error) {
func NewIngressValidator(env ValidatorEnv, ing *v1beta1.Ingress, features []Feature, whiteboxTests []WhiteboxTest, attribs *IngressValidatorAttributes) (*IngressValidator, error) {
var fvs []FeatureValidator
for _, f := range features {
fvs = append(fvs, f.NewValidator())
Expand All @@ -182,18 +182,20 @@ func NewIngressValidator(env ValidatorEnv, ing *v1beta1.Ingress, features []Feat
},
}
return &IngressValidator{
ing: ing,
features: fvs,
attribs: attribs,
client: client,
ing: ing,
features: fvs,
whiteboxTests: whiteboxTests,
attribs: attribs,
client: client,
}, nil
}

// IngressValidator encapsulates the logic required to validate a given configuration
// is behaving correctly.
type IngressValidator struct {
ing *v1beta1.Ingress
features []FeatureValidator
ing *v1beta1.Ingress
features []FeatureValidator
whiteboxTests []WhiteboxTest

attribs *IngressValidatorAttributes
client *http.Client
Expand All @@ -213,6 +215,16 @@ func (v *IngressValidator) vip() *string {
return &ret
}

// PerformWhiteboxTests runs additional whitebox tests.
func (v *IngressValidator) PerformWhiteboxTests(gclb *GCLB) error {
for _, w := range v.whiteboxTests {
if err := w.Test(v.ing, gclb); err != nil {
return fmt.Errorf("%s failed with error: %v", w.Name(), err)
}
}
return nil
}

// Check runs all of the checks against the instantiated load balancer.
func (v *IngressValidator) Check(ctx context.Context) *IngressResult {
glog.V(3).Infof("Check Ingress %s/%s attribs=%+v", v.ing.Namespace, v.ing.Name, v.attribs)
Expand Down
6 changes: 3 additions & 3 deletions pkg/fuzz/validator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ func TestNewIngressValidator(t *testing.T) {
},
} {
t.Run(tc.desc, func(t *testing.T) {
_, err := NewIngressValidator(&MockValidatorEnv{}, tc.ing, tc.features, nil)
_, err := NewIngressValidator(&MockValidatorEnv{}, tc.ing, tc.features, []WhiteboxTest{}, nil)
gotErr := err != nil
if gotErr != tc.wantErr {
t.Errorf("NewIngressValidator() = %v; gotErr = %t, wantErr =%t", err, gotErr, tc.wantErr)
Expand Down Expand Up @@ -309,7 +309,7 @@ func TestValidatorCheck(t *testing.T) {
attribs := defaultAttributes()
attribs.HTTPPort = ms.l.Addr().(*net.TCPAddr).Port
attribs.HTTPSPort = ms.ls.Addr().(*net.TCPAddr).Port
validator, err := NewIngressValidator(&MockValidatorEnv{}, tc.ing, []Feature{}, attribs)
validator, err := NewIngressValidator(&MockValidatorEnv{}, tc.ing, []Feature{}, []WhiteboxTest{}, attribs)
if err != nil {
t.Fatalf("NewIngressValidator(...) = _, %v; want _, nil", err)
}
Expand Down Expand Up @@ -384,7 +384,7 @@ func TestValidatorCheckFeature(t *testing.T) {
attribs.HTTPPort = ms.l.Addr().(*net.TCPAddr).Port
attribs.HTTPSPort = ms.ls.Addr().(*net.TCPAddr).Port

validator, err := NewIngressValidator(&MockValidatorEnv{}, tc.ing, []Feature{tc.feature}, attribs)
validator, err := NewIngressValidator(&MockValidatorEnv{}, tc.ing, []Feature{tc.feature}, []WhiteboxTest{}, attribs)
if gotErr := err != nil; gotErr != tc.wantNewValidatorErr {
t.Errorf("NewIngressValidator(...) = _, %v; gotErr = %t, want %t", err, gotErr, tc.wantNewValidatorErr)
}
Expand Down
30 changes: 30 additions & 0 deletions pkg/fuzz/whitebox.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/*
Copyright 2019 The Kubernetes 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 fuzz

import (
"k8s.io/api/extensions/v1beta1"
)

// WhiteboxTest represents a whitebox test than can be run for an Ingress.
// The test validates a part of the Ingress spec against GCE resources.
type WhiteboxTest interface {
// Name of the test.
Name() string
// Test is the test to run.
Test(ing *v1beta1.Ingress, gclb *GCLB) error
}
57 changes: 57 additions & 0 deletions pkg/fuzz/whitebox/num_backend_services.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
/*
Copyright 2019 The Kubernetes 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 whitebox

import (
"fmt"

"k8s.io/api/extensions/v1beta1"

"k8s.io/ingress-gce/pkg/fuzz"
"k8s.io/ingress-gce/pkg/utils"
)

// Implements a whitebox test to check that the GCLB has the expected number of BackendService's.
type numBackendServicesTest struct {
uniqSvcPorts map[utils.ServicePortID]bool
}

// Name implements WhiteboxTest.
func (t *numBackendServicesTest) Name() string {
return "NumBackendServicesTest"

}

// Test implements WhiteboxTest.
func (t *numBackendServicesTest) Test(ing *v1beta1.Ingress, gclb *fuzz.GCLB) error {
t.uniqSvcPorts = make(map[utils.ServicePortID]bool)
expectedBackendServices := 0

utils.TraverseIngressBackends(ing, func(id utils.ServicePortID) bool {
if _, ok := t.uniqSvcPorts[id]; !ok {
expectedBackendServices++
t.uniqSvcPorts[id] = true
}
return false
})

if len(gclb.BackendService) != expectedBackendServices {
return fmt.Errorf("Expected %d BackendService's but got %d", expectedBackendServices, len(gclb.BackendService))
}

return nil
}
55 changes: 55 additions & 0 deletions pkg/fuzz/whitebox/num_forwarding_rules.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/*
Copyright 2019 The Kubernetes 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 whitebox

import (
"fmt"

"k8s.io/api/extensions/v1beta1"

"k8s.io/ingress-gce/pkg/fuzz"
"k8s.io/ingress-gce/pkg/annotations"
)

// Implements a whitebox test to check that the GCLB has the expected number of ForwardingRule's.
type numForwardingRulesTest struct {
}

// Name implements WhiteboxTest.
func (t *numForwardingRulesTest) Name() string {
return "NumForwardingRulesTest"

}

// Test implements WhiteboxTest.
func (t *numForwardingRulesTest) Test(ing *v1beta1.Ingress, gclb *fuzz.GCLB) error {
expectedForwardingRules := 1
if len(ing.Spec.TLS) > 0 {
expectedForwardingRules = 2
}

an := annotations.FromIngress(ing)
if an.UseNamedTLS() != "" {
expectedForwardingRules = 2
}

if len(gclb.ForwardingRule) != expectedForwardingRules {
return fmt.Errorf("Expected %d ForwardingRule's but got %d", expectedForwardingRules, len(gclb.ForwardingRule))
}

return nil
}
Loading

0 comments on commit 56f650a

Please sign in to comment.