Skip to content

Commit ec47819

Browse files
committed
refactor komega package
rename Matcher to komega since it's not really a matcher komega.With... methods now return copies allow to specify a Gomega instance to use
1 parent c472f24 commit ec47819

File tree

6 files changed

+379
-266
lines changed

6 files changed

+379
-266
lines changed

pkg/envtest/komega/default.go

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package komega
2+
3+
import (
4+
"sigs.k8s.io/controller-runtime/pkg/client"
5+
)
6+
7+
// defaultK is the Komega used by the package global functions.
8+
var defaultK = &komega{}
9+
10+
// SetDefaultClient sets the client used by the package global functions.
11+
func SetDefaultClient(c client.Client) {
12+
defaultK = &komega{client: c}
13+
}
14+
15+
func checkDefaultClient() {
16+
if defaultK.client == nil {
17+
panic("Default Komega's client is not set. Use WithDefaultClient to set it.")
18+
}
19+
}
20+
21+
// Get fetches an object until the forwarded error matches.
22+
func Get(obj client.Object) func() error {
23+
checkDefaultClient()
24+
return defaultK.Get(obj)
25+
}
26+
27+
// List fetches a list until the forwarded error matches.
28+
func List(obj client.ObjectList, opts ...client.ListOption) func() error {
29+
checkDefaultClient()
30+
return defaultK.List(obj, opts...)
31+
}
32+
33+
// Update tries to update an object by applying the updateFunc until the forwarded error matches.
34+
func Update(obj client.Object, f UpdateFunc, opts ...client.UpdateOption) func() error {
35+
checkDefaultClient()
36+
return defaultK.Update(obj, f, opts...)
37+
}
38+
39+
// UpdateStatus tries to update an object's status by applying the updateFunc until the forwarded error matches.
40+
func UpdateStatus(obj client.Object, f UpdateFunc, opts ...client.UpdateOption) func() error {
41+
checkDefaultClient()
42+
return defaultK.UpdateStatus(obj, f, opts...)
43+
}
44+
45+
// Object
46+
func Object(obj client.Object) func() (client.Object, error) {
47+
checkDefaultClient()
48+
return defaultK.Object(obj)
49+
}
50+
51+
// ObjectList
52+
func ObjectList(obj client.ObjectList, opts ...client.ListOption) func() (client.ObjectList, error) {
53+
checkDefaultClient()
54+
return defaultK.ObjectList(obj, opts...)
55+
}

pkg/envtest/komega/interfaces.go

Lines changed: 50 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,39 +18,64 @@ package komega
1818

1919
import (
2020
"context"
21-
"time"
2221

23-
"github.com/onsi/gomega"
24-
"k8s.io/apimachinery/pkg/runtime"
2522
"sigs.k8s.io/controller-runtime/pkg/client"
2623
)
2724

2825
// Komega is the root interface that the Matcher implements.
2926
type Komega interface {
30-
KomegaAsync
31-
KomegaSync
32-
WithContext(context.Context) Komega
33-
}
27+
// Get returns a function that fetches a resource and returns the occuring error.
28+
// It can be used with gomega.Eventually() like this
29+
// deployment := appsv1.Deployment{ ... }
30+
// gomega.Eventually(k.Get(&deployment)).To(gomega.Succeed())
31+
// By calling the returned function directly it can also be used with gomega.Expect(k.Get(...)()).To(...)
32+
Get(client.Object) func() error
3433

35-
// KomegaSync is the interface for any sync assertions that
36-
// the matcher implements.
37-
type KomegaSync interface {
38-
Create(client.Object, ...client.CreateOption) gomega.GomegaAssertion
39-
Delete(client.Object, ...client.DeleteOption) gomega.GomegaAssertion
40-
WithExtras(...interface{}) KomegaSync
41-
}
34+
// List returns a function that lists resources and returns the occuring error.
35+
// It can be used with gomega.Eventually() like this
36+
// deployments := v1.DeploymentList{ ... }
37+
// gomega.Eventually(k.List(&deployments)).To(gomega.Succeed())
38+
// By calling the returned function directly it can also be used as gomega.Expect(k.List(...)()).To(...)
39+
List(client.ObjectList, ...client.ListOption) func() error
40+
41+
// Update returns a function that fetches a resource, applies the provided update function and then updates the resource.
42+
// It can be used with gomega.Eventually() like this:
43+
// deployment := appsv1.Deployment{ ... }
44+
// gomega.Eventually(k.Update(&deployment, func (o client.Object) {
45+
// deployment.Spec.Replicas = 3
46+
// return &deployment
47+
// })).To(gomega.Scucceed())
48+
// By calling the returned function directly it can also be used as gomega.Expect(k.Update(...)()).To(...)
49+
Update(client.Object, UpdateFunc, ...client.UpdateOption) func() error
4250

43-
// KomegaAsync is the interface for any async assertions that
44-
// the matcher implements.
45-
type KomegaAsync interface {
46-
Consistently(runtime.Object, ...client.ListOption) gomega.AsyncAssertion
47-
Eventually(runtime.Object, ...client.ListOption) gomega.AsyncAssertion
48-
Get(client.Object) gomega.AsyncAssertion
49-
List(client.ObjectList, ...client.ListOption) gomega.AsyncAssertion
50-
Update(client.Object, UpdateFunc, ...client.UpdateOption) gomega.AsyncAssertion
51-
UpdateStatus(client.Object, UpdateFunc, ...client.UpdateOption) gomega.AsyncAssertion
52-
WithTimeout(time.Duration) KomegaAsync
53-
WithPollInterval(time.Duration) KomegaAsync
51+
// UpdateStatus returns a function that fetches a resource, applies the provided update function and then updates the resource's status.
52+
// It can be used with gomega.Eventually() like this:
53+
// deployment := appsv1.Deployment{ ... }
54+
// gomega.Eventually(k.Update(&deployment, func (o client.Object) {
55+
// deployment.Status.AvailableReplicas = 1
56+
// return &deployment
57+
// })).To(gomega.Scucceed())
58+
// By calling the returned function directly it can also be used as gomega.Expect(k.UpdateStatus(...)()).To(...)
59+
UpdateStatus(client.Object, UpdateFunc, ...client.UpdateOption) func() error
60+
61+
// Object returns a function that fetches a resource and returns the object.
62+
// It can be used with gomega.Eventually() like this:
63+
// deployment := appsv1.Deployment{ ... }
64+
// gomega.Eventually(k.Object(&deployment)).To(HaveField("Spec.Replicas", gomega.Equal(pointer.Int32(3))))
65+
// By calling the returned function directly it can also be used as gomega.Expect(k.Object(...)()).To(...)
66+
Object(client.Object) func() (client.Object, error)
67+
68+
// ObjectList returns a function that fetches a resource and returns the object.
69+
// It can be used with gomega.Eventually() like this:
70+
// deployments := appsv1.DeploymentList{ ... }
71+
// gomega.Eventually(k.ObjectList(&deployments)).To(HaveField("Items", HaveLen(1)))
72+
// By calling the returned function directly it can also be used as gomega.Expect(k.ObjectList(...)()).To(...)
73+
ObjectList(client.ObjectList, ...client.ListOption) func() (client.ObjectList, error)
74+
75+
// WithClient returns a copy that uses the given client.
76+
WithClient(client.Client) Komega
77+
// WithContext returns a copy that uses the given context.
78+
WithContext(context.Context) Komega
5479
}
5580

5681
// UpdateFunc modifies the object fetched from the API server before sending

pkg/envtest/komega/komega.go

Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
Copyright 2021 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package komega
18+
19+
import (
20+
"context"
21+
22+
"k8s.io/apimachinery/pkg/types"
23+
"sigs.k8s.io/controller-runtime/pkg/client"
24+
)
25+
26+
// komega is a collection of
27+
type komega struct {
28+
ctx context.Context
29+
client client.Client
30+
}
31+
32+
var _ Komega = &komega{}
33+
34+
// New creates a new Komega instance with the given client.
35+
func New(c client.Client) Komega {
36+
return &komega{
37+
client: c,
38+
}
39+
}
40+
41+
// WithContext returns a copy that uses the given context.
42+
func (k komega) WithContext(ctx context.Context) Komega {
43+
k.ctx = ctx
44+
return &k
45+
}
46+
47+
// WithClient returns a copy that uses the given client.
48+
func (k komega) WithClient(c client.Client) Komega {
49+
k.client = c
50+
return &k
51+
}
52+
53+
// context returns the matcher context if one has been set or context.Background() otherwise.
54+
func (k *komega) context() context.Context {
55+
if k.ctx == nil {
56+
return context.Background()
57+
}
58+
return k.ctx
59+
}
60+
61+
// Get returns a function that fetches a resource and returns the occuring error.
62+
func (k *komega) Get(obj client.Object) func() error {
63+
key := types.NamespacedName{
64+
Name: obj.GetName(),
65+
Namespace: obj.GetNamespace(),
66+
}
67+
return func() error {
68+
return k.client.Get(k.context(), key, obj)
69+
}
70+
}
71+
72+
// List returns a function that lists resources and returns the occuring error.
73+
func (k *komega) List(obj client.ObjectList, opts ...client.ListOption) func() error {
74+
return func() error {
75+
return k.client.List(k.context(), obj, opts...)
76+
}
77+
}
78+
79+
// Update returns a function that fetches a resource, applies the provided update function and then updates the resource.
80+
func (k *komega) Update(obj client.Object, updateFunc UpdateFunc, opts ...client.UpdateOption) func() error {
81+
key := types.NamespacedName{
82+
Name: obj.GetName(),
83+
Namespace: obj.GetNamespace(),
84+
}
85+
return func() error {
86+
err := k.client.Get(k.context(), key, obj)
87+
if err != nil {
88+
return err
89+
}
90+
return k.client.Update(k.context(), updateFunc(obj), opts...)
91+
}
92+
}
93+
94+
// UpdateStatus returns a function that fetches a resource, applies the provided update function and then updates the resource's status.
95+
func (k *komega) UpdateStatus(obj client.Object, updateFunc UpdateFunc, opts ...client.UpdateOption) func() error {
96+
key := types.NamespacedName{
97+
Name: obj.GetName(),
98+
Namespace: obj.GetNamespace(),
99+
}
100+
return func() error {
101+
err := k.client.Get(k.context(), key, obj)
102+
if err != nil {
103+
return err
104+
}
105+
return k.client.Status().Update(k.context(), updateFunc(obj), opts...)
106+
}
107+
}
108+
109+
// Object returns a function that fetches a resource and returns the object.
110+
func (k *komega) Object(obj client.Object) func() (client.Object, error) {
111+
key := types.NamespacedName{
112+
Name: obj.GetName(),
113+
Namespace: obj.GetNamespace(),
114+
}
115+
return func() (client.Object, error) {
116+
err := k.client.Get(k.context(), key, obj)
117+
return obj, err
118+
}
119+
}
120+
121+
// ObjectList returns a function that fetches a resource and returns the object.
122+
func (k *komega) ObjectList(obj client.ObjectList, opts ...client.ListOption) func() (client.ObjectList, error) {
123+
return func() (client.ObjectList, error) {
124+
err := k.client.List(k.context(), obj, opts...)
125+
return obj, err
126+
}
127+
}

0 commit comments

Comments
 (0)