diff --git a/pkg/client/options.go b/pkg/client/options.go index 50a461f1cc..32bdbac3e1 100644 --- a/pkg/client/options.go +++ b/pkg/client/options.go @@ -513,7 +513,18 @@ type MatchingLabels map[string]string // ApplyToList applies this configuration to the given list options. func (m MatchingLabels) ApplyToList(opts *ListOptions) { // TODO(directxman12): can we avoid reserializing this over and over? - sel := labels.SelectorFromValidatedSet(map[string]string(m)) + var sel labels.Selector + if opts.LabelSelector != nil { + sel = opts.LabelSelector + } else { + sel = labels.NewSelector() + } + // If there's already a selector, we need to AND the two together. + noValidSel := labels.SelectorFromValidatedSet(map[string]string(m)) + reqs, _ := noValidSel.Requirements() + for _, req := range reqs { + sel = sel.Add(req) + } opts.LabelSelector = sel } @@ -528,7 +539,14 @@ type HasLabels []string // ApplyToList applies this configuration to the given list options. func (m HasLabels) ApplyToList(opts *ListOptions) { - sel := labels.NewSelector() + var sel labels.Selector + if opts.LabelSelector != nil { + sel = opts.LabelSelector + } else { + sel = labels.NewSelector() + } + // TODO: ignore invalid labels will result in empty selector. + // This is not consistent to the MatchingLabels behavior. for _, label := range m { r, err := labels.NewRequirement(label, selection.Exists, nil) if err == nil { diff --git a/pkg/client/options_test.go b/pkg/client/options_test.go index efba976c4f..4850b9121f 100644 --- a/pkg/client/options_test.go +++ b/pkg/client/options_test.go @@ -237,6 +237,19 @@ var _ = Describe("MatchingLabels", func() { expectedErrMsg := `values[0][k]: Invalid value: "axahm2EJ8Phiephe2eixohbee9eGeiyees1thuozi1xoh0GiuH3diewi8iem7Nui": must be no more than 63 characters` Expect(err.Error()).To(Equal(expectedErrMsg)) }) + + It("Should add matchingLabels to existing selector", func() { + listOpts := &client.ListOptions{} + + matchingLabels := client.MatchingLabels(map[string]string{"k": "v"}) + matchingLabels2 := client.MatchingLabels(map[string]string{"k2": "v2"}) + + matchingLabels.ApplyToList(listOpts) + Expect(listOpts.LabelSelector.String()).To(Equal("k=v")) + + matchingLabels2.ApplyToList(listOpts) + Expect(listOpts.LabelSelector.String()).To(Equal("k=v,k2=v2")) + }) }) var _ = Describe("FieldOwner", func() { @@ -292,3 +305,45 @@ var _ = Describe("ForceOwnership", func() { Expect(*o.Force).To(Equal(true)) }) }) + +var _ = Describe("HasLabels", func() { + const invalidLongKey = "axahm2EJ8Phiephe2eixohbee9eGeiyees1thuozi1xoh0GiuH3diewi8iem7Nui" + + It("Should produce hasLabels in given order", func() { + listOpts := &client.ListOptions{} + + hasLabels := client.HasLabels([]string{"labelApe", "labelFox"}) + hasLabels.ApplyToList(listOpts) + Expect(listOpts.LabelSelector.String()).To(Equal("labelApe,labelFox")) + }) + + It("Should produce an empty selector when given invalid input", func() { + listOpts := &client.ListOptions{} + // construct a valid hasLabels selector + hasLabel := client.HasLabels([]string{invalidLongKey}) + hasLabel.ApplyToList(listOpts) + Expect(listOpts.LabelSelector.Empty()).To(BeTrue()) + }) + + It("Should add hasLabels to existing hasLabels selector", func() { + listOpts := &client.ListOptions{} + + hasLabel := client.HasLabels([]string{"labelApe"}) + hasLabel.ApplyToList(listOpts) + + hasOtherLabel := client.HasLabels([]string{"labelFox"}) + hasOtherLabel.ApplyToList(listOpts) + Expect(listOpts.LabelSelector.String()).To(Equal("labelApe,labelFox")) + }) + + It("Should add hasLabels to existing matchingLabels", func() { + listOpts := &client.ListOptions{} + + matchingLabels := client.MatchingLabels(map[string]string{"k": "v"}) + matchingLabels.ApplyToList(listOpts) + + hasLabel := client.HasLabels([]string{"labelApe"}) + hasLabel.ApplyToList(listOpts) + Expect(listOpts.LabelSelector.String()).To(Equal("k=v,labelApe")) + }) +})