Add Generation variants of kmeta/labels.go (#117)

Unlike `ResourceVersion`, which changes whenever the resource changes at all (including `/status` which can be high churn), `Generation` only changes when the `/spec` of a CRD changes (for CRDs starting in 1.11, right now they are locked at `generation: 1`).

These methods are useful for interacting with K8s resource now, and will be useful for CRDs soon.

Fixes: https://github.com/knative/pkg/issues/116
This commit is contained in:
Matt Moore 2018-10-08 02:14:25 -07:00 committed by Knative Prow Robot
parent 1f153817b2
commit 1a50a39daf
2 changed files with 131 additions and 0 deletions

View File

@ -26,6 +26,13 @@ import (
// The methods in this file are used for managing subresources in cases where
// a controller instantiates different resources for each version of itself.
// There are two sets of methods available here:
// * `*VersionLabel*`: these methods act on `metadata.resourceVersion` and
// create new labels for EVERY change to the resource (incl. `/status`).
// * `*GenerationLabel*`: these methods act on `metadata.generation` and
// create new labels for changes to the resource's "spec" (typically, but
// some K8s resources change `metadata.generation` for annotations as well
// e.g. Deployment).
//
// For example, if an A might instantiate N B's at version 1 and M B's at
// version 2 then it can use MakeVersionLabels to decorate each subresource
@ -66,6 +73,37 @@ func MakeOldVersionLabelSelector(om metav1.ObjectMetaAccessor) labels.Selector {
)
}
// MakeGenerationLabels constructs a set of labels to apply to subresources
// instantiated at this version of the parent resource, so that we can
// efficiently select them.
func MakeGenerationLabels(om metav1.ObjectMetaAccessor) labels.Set {
return map[string]string{
"controller": string(om.GetObjectMeta().GetUID()),
"generation": genStr(om),
}
}
// MakeGenerationLabelSelector constructs a selector for subresources
// instantiated at this version of the parent resource. This keys
// off of the labels populated by MakeGenerationLabels.
func MakeGenerationLabelSelector(om metav1.ObjectMetaAccessor) labels.Selector {
return labels.SelectorFromSet(MakeGenerationLabels(om))
}
// MakeOldGenerationLabelSelector constructs a selector for subresources
// instantiated at an older version of the parent resource. This keys
// off of the labels populated by MakeGenerationLabels.
func MakeOldGenerationLabelSelector(om metav1.ObjectMetaAccessor) labels.Selector {
return labels.NewSelector().Add(
mustNewRequirement("controller", selection.Equals, []string{string(om.GetObjectMeta().GetUID())}),
mustNewRequirement("generation", selection.NotEquals, []string{genStr(om)}),
)
}
func genStr(om metav1.ObjectMetaAccessor) string {
return fmt.Sprintf("%05d", om.GetObjectMeta().GetGeneration())
}
// mustNewRequirement panics if there are any errors constructing our selectors.
func mustNewRequirement(key string, op selection.Operator, vals []string) labels.Requirement {
r, err := labels.NewRequirement(key, op, vals)

View File

@ -114,3 +114,96 @@ func TestMakeOldVersionLabelSelector(t *testing.T) {
})
}
}
func TestMakeGenerationLabels(t *testing.T) {
tests := []struct {
name string
om metav1.ObjectMeta
s string
}{{
name: "simple translation",
om: metav1.ObjectMeta{
UID: "1234",
Generation: 5,
},
s: "controller=1234,generation=00005",
}, {
name: "another simple translation",
om: metav1.ObjectMeta{
UID: "abcd",
Generation: 5432,
},
s: "controller=abcd,generation=05432",
}}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ls := MakeGenerationLabels(&test.om)
if want, got := test.s, ls.String(); got != want {
t.Errorf("MakeGenerationLabels() = %v, wanted %v", got, want)
}
})
}
}
func TestMakeGenerationLabelSelector(t *testing.T) {
tests := []struct {
name string
om metav1.ObjectMeta
s string
}{{
name: "simple translation",
om: metav1.ObjectMeta{
UID: "1234",
Generation: 5,
},
s: "controller=1234,generation=00005",
}, {
name: "another simple translation",
om: metav1.ObjectMeta{
UID: "abcd",
Generation: 5432,
},
s: "controller=abcd,generation=05432",
}}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ls := MakeGenerationLabelSelector(&test.om)
if want, got := test.s, ls.String(); got != want {
t.Errorf("MakeGenerationLabelSelector() = %v, wanted %v", got, want)
}
})
}
}
func TestMakeOldGenerationLabelSelector(t *testing.T) {
tests := []struct {
name string
om metav1.ObjectMeta
s string
}{{
name: "simple translation",
om: metav1.ObjectMeta{
UID: "1234",
Generation: 5,
},
s: "controller=1234,generation!=00005",
}, {
name: "another simple translation",
om: metav1.ObjectMeta{
UID: "abcd",
Generation: 5432,
},
s: "controller=abcd,generation!=05432",
}}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
ls := MakeOldGenerationLabelSelector(&test.om)
if want, got := test.s, ls.String(); got != want {
t.Errorf("MakeOldGenerationLabelSelector() = %v, wanted %v", got, want)
}
})
}
}