Skip to content

Commit c066965

Browse files
authored
minor improvements (includes release v0.8.0) (#46)
* add LabelSelectorPredicate function to controller library * add method to simply create fake Clusters for testing purposes * enable clusters package to add --kubeconfig flag * release v0.8.0
1 parent c9a3b4a commit c066965

File tree

4 files changed

+68
-1
lines changed

4 files changed

+68
-1
lines changed

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.7.0-dev
1+
v0.8.0

pkg/clusters/cluster.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,16 @@ func New(id string) *Cluster {
3636
return c
3737
}
3838

39+
// NewTestClusterFromClient creates a Cluster from a given client.
40+
// Note that this method is meant for testing purposes only and it does not result in a fully functional Cluster.
41+
// Calling anything except Client() on the resulting Cluster is undefined and might lead to panics or unexpected behavior.
42+
func NewTestClusterFromClient(id string, cli client.Client) *Cluster {
43+
c := &Cluster{}
44+
c.InitializeID(id)
45+
c.client = cli
46+
return c
47+
}
48+
3949
// WithConfigPath sets the config path for the cluster.
4050
// Returns the cluster for chaining.
4151
func (c *Cluster) WithConfigPath(cfgPath string) *Cluster {
@@ -51,6 +61,7 @@ func (c *Cluster) WithRESTConfig(cfg *rest.Config) *Cluster {
5161
}
5262

5363
// RegisterConfigPathFlag adds a flag '--<id>-cluster' for the cluster's config path to the given flag set.
64+
// If only a single kubeconfig is required, RegisterSingleConfigPathFlag can be used instead to have the flag named '--kubeconfig'.
5465
// Panics if the cluster's id is not set.
5566
func (c *Cluster) RegisterConfigPathFlag(flags *flag.FlagSet) {
5667
if !c.HasID() {
@@ -59,6 +70,12 @@ func (c *Cluster) RegisterConfigPathFlag(flags *flag.FlagSet) {
5970
flags.StringVar(&c.cfgPath, fmt.Sprintf("%s-cluster", c.id), "", fmt.Sprintf("Path to the %s cluster kubeconfig file or directory containing either a kubeconfig or host, token, and ca file. Leave empty to use in-cluster config.", c.id))
6071
}
6172

73+
// RegisterSingleConfigPathFlag adds a '--kubeconfig' flag for the cluster's config path to the given flag set.
74+
// If more than one kubeconfig is required, consider using RegisterConfigPathFlag instead, which is identical, but names the flag '--<id>-cluster'.
75+
func (c *Cluster) RegisterSingleConfigPathFlag(flags *flag.FlagSet) {
76+
flags.StringVar(&c.cfgPath, "kubeconfig", "", "Path to the kubeconfig file or directory containing either a kubeconfig or host, token, and ca file. Leave empty to use in-cluster config.")
77+
}
78+
6279
// WithClientOptions allows to overwrite the default client options.
6380
// It must be called before InitializeClient().
6481
// Note that using this method disables the the scheme injection during client initialization.

pkg/controller/predicates.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ package controller
55
import (
66
"reflect"
77

8+
"k8s.io/apimachinery/pkg/labels"
89
"sigs.k8s.io/controller-runtime/pkg/client"
910
"sigs.k8s.io/controller-runtime/pkg/event"
1011
"sigs.k8s.io/controller-runtime/pkg/predicate"
@@ -179,6 +180,22 @@ func LostLabelPredicate(key, val string) predicate.Predicate {
179180
}
180181
}
181182

183+
// LabelSelectorPredicate returns a predicate based on a label selector.
184+
// Opposed to the similarly named function from the controller-runtime library, this one works on label.Selector
185+
// instead of metav1.LabelSelector.
186+
func LabelSelectorPredicate(sel labels.Selector) predicate.Predicate {
187+
return predicate.NewPredicateFuncs(func(obj client.Object) bool {
188+
if obj == nil {
189+
return false
190+
}
191+
ls := obj.GetLabels()
192+
if ls == nil {
193+
ls = map[string]string{}
194+
}
195+
return sel.Matches(labels.Set(ls))
196+
})
197+
}
198+
182199
/////////////////////////
183200
/// STATUS PREDICATES ///
184201
/////////////////////////

pkg/controller/predicates_test.go

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import (
66

77
corev1 "k8s.io/api/core/v1"
88
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
9+
"k8s.io/apimachinery/pkg/labels"
910
"k8s.io/utils/ptr"
1011
"sigs.k8s.io/controller-runtime/pkg/client"
1112
"sigs.k8s.io/controller-runtime/pkg/event"
@@ -114,8 +115,24 @@ var _ = Describe("Predicates", func() {
114115
It("should detect changes to the labels", func() {
115116
pHasFoo := ctrlutils.HasLabelPredicate("foo", "")
116117
pHasBar := ctrlutils.HasLabelPredicate("bar", "")
118+
matchesEverything := ctrlutils.LabelSelectorPredicate(labels.Everything())
119+
matchesNothing := ctrlutils.LabelSelectorPredicate(labels.Nothing())
117120
pHasFooWithFoo := ctrlutils.HasLabelPredicate("foo", "foo")
118121
pHasFooWithBar := ctrlutils.HasLabelPredicate("foo", "bar")
122+
fooWithFooSelector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{
123+
MatchLabels: map[string]string{
124+
"foo": "foo",
125+
},
126+
})
127+
Expect(err).ToNot(HaveOccurred())
128+
fooWithBarSelector, err := metav1.LabelSelectorAsSelector(&metav1.LabelSelector{
129+
MatchLabels: map[string]string{
130+
"foo": "bar",
131+
},
132+
})
133+
Expect(err).ToNot(HaveOccurred())
134+
pHasFooWithFooViaSelector := ctrlutils.LabelSelectorPredicate(fooWithFooSelector)
135+
pHasFooWithBarViaSelector := ctrlutils.LabelSelectorPredicate(fooWithBarSelector)
119136
pGotFoo := ctrlutils.GotLabelPredicate("foo", "")
120137
pGotFooWithFoo := ctrlutils.GotLabelPredicate("foo", "foo")
121138
pGotFooWithBar := ctrlutils.GotLabelPredicate("foo", "bar")
@@ -124,9 +141,13 @@ var _ = Describe("Predicates", func() {
124141
pLostFooWithBar := ctrlutils.LostLabelPredicate("foo", "bar")
125142
By("old and new resource are equal")
126143
e := updateEvent(base, changed)
144+
Expect(matchesEverything.Update(e)).To(BeTrue(), "'everything' LabelSelector should always match")
145+
Expect(matchesNothing.Update(e)).To(BeFalse(), "'nothing' LabelSelector should never match")
127146
Expect(pHasFoo.Update(e)).To(BeFalse(), "HasLabelPredicate should return false if there are no labels")
128147
Expect(pHasFooWithFoo.Update(e)).To(BeFalse(), "HasLabelPredicate should return false if there are no labels")
148+
Expect(pHasFooWithFooViaSelector.Update(e)).To(BeFalse(), "LabelSelectorPredicate should return false if the labels are not matched")
129149
Expect(pHasFooWithBar.Update(e)).To(BeFalse(), "HasLabelPredicate should return false if there are no labels")
150+
Expect(pHasFooWithBarViaSelector.Update(e)).To(BeFalse(), "LabelSelectorPredicate should return falseif the labels are not matched")
130151
Expect(pGotFoo.Update(e)).To(BeFalse(), "GotLabelPredicate should return false if there are no labels")
131152
Expect(pGotFooWithFoo.Update(e)).To(BeFalse(), "GotLabelPredicate should return false if there are no labels")
132153
Expect(pGotFooWithBar.Update(e)).To(BeFalse(), "GotLabelPredicate should return false if there are no labels")
@@ -138,10 +159,14 @@ var _ = Describe("Predicates", func() {
138159
"foo": "foo",
139160
})
140161
e = updateEvent(base, changed)
162+
Expect(matchesEverything.Update(e)).To(BeTrue(), "'everything' LabelSelector should always match")
163+
Expect(matchesNothing.Update(e)).To(BeFalse(), "'nothing' LabelSelector should never match")
141164
Expect(pHasFoo.Update(e)).To(BeTrue(), "HasLabelPredicate should return true if the label is there")
142165
Expect(pHasBar.Update(e)).To(BeFalse(), "HasLabelPredicate should return false if the label is not there")
143166
Expect(pHasFooWithFoo.Update(e)).To(BeTrue(), "HasLabelPredicate should return true if the label is there and has the fitting value")
167+
Expect(pHasFooWithFooViaSelector.Update(e)).To(BeTrue(), "LabelSelectorPredicate should return true if the labels are matched")
144168
Expect(pHasFooWithBar.Update(e)).To(BeFalse(), "HasLabelPredicate should return false if the label is there but has the wrong value")
169+
Expect(pHasFooWithBarViaSelector.Update(e)).To(BeFalse(), "LabelSelectorPredicate should return false if the labels are not matched")
145170
Expect(pGotFoo.Update(e)).To(BeTrue(), "GotLabelPredicate should return true if the label was added")
146171
Expect(pGotFooWithFoo.Update(e)).To(BeTrue(), "GotLabelPredicate should return true if the label was added with the correct value")
147172
Expect(pGotFooWithBar.Update(e)).To(BeFalse(), "GotLabelPredicate should return false if the label was added but with the wrong value")
@@ -154,10 +179,14 @@ var _ = Describe("Predicates", func() {
154179
"foo": "bar",
155180
})
156181
e = updateEvent(base, changed)
182+
Expect(matchesEverything.Update(e)).To(BeTrue(), "'everything' LabelSelector should always match")
183+
Expect(matchesNothing.Update(e)).To(BeFalse(), "'nothing' LabelSelector should never match")
157184
Expect(pHasFoo.Update(e)).To(BeTrue(), "HasLabelPredicate should return true if the label is there")
158185
Expect(pHasBar.Update(e)).To(BeFalse(), "HasLabelPredicate should return false if the label is not there")
159186
Expect(pHasFooWithFoo.Update(e)).To(BeFalse(), "HasLabelPredicate should return false if the label is there but has the wrong value")
187+
Expect(pHasFooWithFooViaSelector.Update(e)).To(BeFalse(), "LabelSelectorPredicate should return false if the labels are not matched")
160188
Expect(pHasFooWithBar.Update(e)).To(BeTrue(), "HasLabelPredicate should return true if the label is there and has the fitting value")
189+
Expect(pHasFooWithBarViaSelector.Update(e)).To(BeTrue(), "LabelSelectorPredicate should return true if the labels are matched")
161190
Expect(pGotFoo.Update(e)).To(BeFalse(), "GotLabelPredicate should return false if the label was there before")
162191
Expect(pGotFooWithFoo.Update(e)).To(BeFalse(), "GotLabelPredicate should return false if the label was changed but to the wrong value")
163192
Expect(pGotFooWithBar.Update(e)).To(BeTrue(), "GotLabelPredicate should return true if the label was changed to the correct value")
@@ -168,9 +197,13 @@ var _ = Describe("Predicates", func() {
168197
base = changed.DeepCopy()
169198
changed.SetLabels(nil)
170199
e = updateEvent(base, changed)
200+
Expect(matchesEverything.Update(e)).To(BeTrue(), "'everything' LabelSelector should always match")
201+
Expect(matchesNothing.Update(e)).To(BeFalse(), "'nothing' LabelSelector should never match")
171202
Expect(pHasFoo.Update(e)).To(BeFalse(), "HasLabelPredicate should return false if there are no labels")
172203
Expect(pHasFooWithFoo.Update(e)).To(BeFalse(), "HasLabelPredicate should return false if there are no labels")
204+
Expect(pHasFooWithFooViaSelector.Update(e)).To(BeFalse(), "LabelSelectorPredicate should return false if the labels are not matched")
173205
Expect(pHasFooWithBar.Update(e)).To(BeFalse(), "HasLabelPredicate should return false if there are no labels")
206+
Expect(pHasFooWithBarViaSelector.Update(e)).To(BeFalse(), "LabelSelectorPredicate should return false if the labels are not matched")
174207
Expect(pGotFoo.Update(e)).To(BeFalse(), "GotLabelPredicate should return false if there are no labels")
175208
Expect(pGotFooWithFoo.Update(e)).To(BeFalse(), "GotLabelPredicate should return false if there are no labels")
176209
Expect(pGotFooWithBar.Update(e)).To(BeFalse(), "GotLabelPredicate should return false if there are no labels")

0 commit comments

Comments
 (0)