Skip to content

Commit

Permalink
test(catalog): add sync resolving namespace benchmark
Browse files Browse the repository at this point in the history
  • Loading branch information
njhale committed Jul 2, 2019
1 parent 49690b7 commit 9145945
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 19 deletions.
34 changes: 26 additions & 8 deletions pkg/controller/operators/catalog/operator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
"k8s.io/client-go/rest"
"k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1"
apiextensionsfake "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/fake"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -24,6 +23,7 @@ import (
utilclock "k8s.io/apimachinery/pkg/util/clock"
"k8s.io/client-go/informers"
k8sfake "k8s.io/client-go/kubernetes/fake"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
apiregistrationfake "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/fake"
Expand Down Expand Up @@ -569,11 +569,25 @@ type fakeOperatorConfig struct {
regObjs []runtime.Object
clientOptions []clientfake.Option
logger *logrus.Logger
resolver resolver.Resolver
reconciler reconciler.RegistryReconcilerFactory
}

// fakeOperatorOption applies an option to the given fake operator configuration.
type fakeOperatorOption func(*fakeOperatorConfig)

func withResolver(res resolver.Resolver) fakeOperatorOption {
return func(config *fakeOperatorConfig) {
config.resolver = res
}
}

func withReconciler(rec reconciler.RegistryReconcilerFactory) fakeOperatorOption {
return func(config *fakeOperatorConfig) {
config.reconciler = rec
}
}

func withClock(clock utilclock.Clock) fakeOperatorOption {
return func(config *fakeOperatorConfig) {
config.clock = clock
Expand Down Expand Up @@ -608,8 +622,9 @@ func withFakeClientOptions(options ...clientfake.Option) fakeOperatorOption {
func NewFakeOperator(ctx context.Context, namespace string, watchedNamespaces []string, fakeOptions ...fakeOperatorOption) (*Operator, error) {
// Apply options to default config
config := &fakeOperatorConfig{
logger: logrus.New(),
clock: utilclock.RealClock{},
logger: logrus.New(),
clock: utilclock.RealClock{},
resolver: &fakes.FakeResolver{},
}
for _, option := range fakeOptions {
option(config)
Expand Down Expand Up @@ -689,12 +704,15 @@ func NewFakeOperator(ctx context.Context, namespace string, watchedNamespaces []
// 1 qps, 100 bucket size. This is only for retry speed and its only the overall factor (not per item)
&workqueue.BucketRateLimiter{Limiter: rate.NewLimiter(rate.Limit(1), 100)},
), "resolver"),
sources: make(map[resolver.CatalogKey]resolver.SourceRef),
resolver: &fakes.FakeResolver{},
clientAttenuator: scoped.NewClientAttenuator(logger, &rest.Config{}, opClientFake, clientFake),
serviceAccountQuerier: scoped.NewUserDefinedServiceAccountQuerier(logger, clientFake),
sources: make(map[resolver.CatalogKey]resolver.SourceRef),
resolver: config.resolver,
reconciler: config.reconciler,
clientAttenuator: scoped.NewClientAttenuator(logger, &rest.Config{}, opClientFake, clientFake),
serviceAccountQuerier: scoped.NewUserDefinedServiceAccountQuerier(logger, clientFake),
}
if op.reconciler == nil {
op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, op.opClient, "test:pod", op.now)
}
op.reconciler = reconciler.NewRegistryReconcilerFactory(lister, op.opClient, "test:pod", op.now)

op.RunInformers(ctx)

Expand Down
156 changes: 149 additions & 7 deletions pkg/controller/operators/catalog/subscriptions_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (
"time"

"github.com/stretchr/testify/require"
v1 "k8s.io/api/core/v1"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
utilclock "k8s.io/apimachinery/pkg/util/clock"
Expand Down Expand Up @@ -139,7 +139,7 @@ func TestSyncSubscriptions(t *testing.T) {
Kind: v1alpha1.InstallPlanKind,
APIVersion: v1alpha1.InstallPlanAPIVersion,
},
InstallPlanRef: &v1.ObjectReference{
InstallPlanRef: &corev1.ObjectReference{
Namespace: testNamespace,
Kind: v1alpha1.InstallPlanKind,
APIVersion: v1alpha1.InstallPlanAPIVersion,
Expand Down Expand Up @@ -270,7 +270,7 @@ func TestSyncSubscriptions(t *testing.T) {
Kind: v1alpha1.InstallPlanKind,
APIVersion: v1alpha1.InstallPlanAPIVersion,
},
InstallPlanRef: &v1.ObjectReference{
InstallPlanRef: &corev1.ObjectReference{
Namespace: testNamespace,
Kind: v1alpha1.InstallPlanKind,
APIVersion: v1alpha1.InstallPlanAPIVersion,
Expand Down Expand Up @@ -410,7 +410,7 @@ func TestSyncSubscriptions(t *testing.T) {
Kind: v1alpha1.InstallPlanKind,
APIVersion: v1alpha1.InstallPlanAPIVersion,
},
InstallPlanRef: &v1.ObjectReference{
InstallPlanRef: &corev1.ObjectReference{
Namespace: testNamespace,
Kind: v1alpha1.InstallPlanKind,
APIVersion: v1alpha1.InstallPlanAPIVersion,
Expand Down Expand Up @@ -574,7 +574,7 @@ func TestSyncSubscriptions(t *testing.T) {
Kind: v1alpha1.InstallPlanKind,
APIVersion: v1alpha1.InstallPlanAPIVersion,
},
InstallPlanRef: &v1.ObjectReference{
InstallPlanRef: &corev1.ObjectReference{
Namespace: testNamespace,
Kind: v1alpha1.InstallPlanKind,
APIVersion: v1alpha1.InstallPlanAPIVersion,
Expand Down Expand Up @@ -645,7 +645,7 @@ func TestSyncSubscriptions(t *testing.T) {
ctx, cancel := context.WithCancel(context.TODO())
defer cancel()

o, err := NewFakeOperator(ctx, testNamespace, []string{testNamespace}, withClock(clockFake), withClientObjs(tt.fields.existingOLMObjs...), withK8sObjs(tt.fields.existingObjects...), withFakeClientOptions(tt.fields.clientOptions...))
o, err := NewFakeOperator(ctx, testNamespace, []string{testNamespace}, withClientObjs(tt.fields.existingOLMObjs...), withK8sObjs(tt.fields.existingObjects...), withFakeClientOptions(tt.fields.clientOptions...))
require.NoError(t, err)

o.reconciler = &fakes.FakeRegistryReconcilerFactory{
Expand All @@ -665,7 +665,7 @@ func TestSyncSubscriptions(t *testing.T) {
},
}

namespace := &v1.Namespace{
namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: testNamespace,
},
Expand All @@ -692,3 +692,145 @@ func TestSyncSubscriptions(t *testing.T) {
})
}
}

type operatorBuilder interface {
operator(ctx context.Context) (*Operator, error)
}

type objs struct {
clientObjs []runtime.Object
k8sObjs []runtime.Object
}

type srnFields struct {
clientOptions []clientfake.Option
existingObjs objs
resolver resolver.Resolver
reconciler reconciler.RegistryReconcilerFactory
}

type srnArgs struct {
namespace string
}

type srnTest struct {
fields srnFields
args srnArgs
}

func (t srnTest) operator(ctx context.Context) (*Operator, error) {
return NewFakeOperator(
ctx,
t.args.namespace,
[]string{t.args.namespace},
withClientObjs(t.fields.existingObjs.clientObjs...),
withK8sObjs(t.fields.existingObjs.k8sObjs...),
withFakeClientOptions(t.fields.clientOptions...),
withResolver(t.fields.resolver),
)
}

func benchOperator(ctx context.Context, test operatorBuilder, b *testing.B) (*Operator, error) {
b.StartTimer()
defer b.StopTimer()

return test.operator(ctx)
}

func benchmarkSyncResolvingNamespace(test srnTest, b *testing.B) {
b.ResetTimer()
for n := 0; n < b.N; n++ {
ctx, cancel := context.WithCancel(context.TODO())
defer cancel()

o, err := benchOperator(ctx, test, b)
require.NoError(b, err)

namespace := &corev1.Namespace{
ObjectMeta: metav1.ObjectMeta{
Name: test.args.namespace,
},
}
require.NoError(b, o.syncResolvingNamespace(namespace))
}
}

func BenchmarkSyncResolvingNamespace(b *testing.B) {
ns := "default"
name := "sub"
benchmarkSyncResolvingNamespace(srnTest{
fields: srnFields{
clientOptions: []clientfake.Option{clientfake.WithSelfLinks(b)},
existingObjs: objs{
clientObjs: []runtime.Object{
&v1alpha1.Subscription{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ns,
},
Spec: &v1alpha1.SubscriptionSpec{
CatalogSource: "src",
CatalogSourceNamespace: ns,
},
Status: v1alpha1.SubscriptionStatus{
CurrentCSV: "",
State: "",
},
},
},
},
reconciler: &fakes.FakeRegistryReconcilerFactory{
ReconcilerForSourceStub: func(*v1alpha1.CatalogSource) reconciler.RegistryReconciler {
return &fakes.FakeRegistryReconciler{
CheckRegistryServerStub: func(*v1alpha1.CatalogSource) (bool, error) {
return true, nil
},
}
},
},
resolver: &fakes.FakeResolver{
ResolveStepsStub: func(string, resolver.SourceQuerier) ([]*v1alpha1.Step, []*v1alpha1.Subscription, error) {
steps := []*v1alpha1.Step{
{
Resolving: "csv.v.2",
Resource: v1alpha1.StepResource{
CatalogSource: "src",
CatalogSourceNamespace: ns,
Group: v1alpha1.GroupName,
Version: v1alpha1.GroupVersion,
Kind: v1alpha1.ClusterServiceVersionKind,
Name: "csv.v.2",
Manifest: "{}",
},
},
}
subs := []*v1alpha1.Subscription{
{
TypeMeta: metav1.TypeMeta{
Kind: v1alpha1.SubscriptionKind,
APIVersion: v1alpha1.SubscriptionCRDAPIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ns,
},
Spec: &v1alpha1.SubscriptionSpec{
CatalogSource: "src",
CatalogSourceNamespace: ns,
},
Status: v1alpha1.SubscriptionStatus{
CurrentCSV: "csv.v.2",
State: "SubscriptionStateAtLatest",
},
},
}

return steps, subs, nil
},
},
},
args: srnArgs{
namespace: ns,
},
}, b)
}
8 changes: 4 additions & 4 deletions pkg/lib/clientfake/client_options.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ import (
type Option func(ClientsetDecorator)

// WithSelfLinks returns a fakeClientOption that configures a ClientsetDecorator to write selfLinks to all OLM types on create.
func WithSelfLinks(t *testing.T) Option {
func WithSelfLinks(tb testing.TB) Option {
return func(c ClientsetDecorator) {
c.PrependReactor("create", "*", func(a clitesting.Action) (bool, runtime.Object, error) {
ca, ok := a.(clitesting.CreateAction)
if !ok {
t.Fatalf("expected CreateAction")
tb.Fatalf("expected CreateAction")
}

obj := ca.GetObject()
Expand All @@ -39,12 +39,12 @@ func WithSelfLinks(t *testing.T) Option {
}

// WithNameGeneration returns a fakeK8sClientOption that configures a Clientset to write generated names to all types on create.
func WithNameGeneration(t *testing.T) Option {
func WithNameGeneration(tb testing.TB) Option {
return func(c ClientsetDecorator) {
c.PrependReactor("create", "*", func(a clitesting.Action) (bool, runtime.Object, error) {
ca, ok := a.(clitesting.CreateAction)
if !ok {
t.Fatalf("expected CreateAction")
tb.Fatalf("expected CreateAction")
}

return false, AddSimpleGeneratedName(ca.GetObject()), nil
Expand Down

0 comments on commit 9145945

Please sign in to comment.