Merge "Add kyaml Label selector to document plugins"

This commit is contained in:
Zuul 2021-04-29 22:02:56 +00:00 committed by Gerrit Code Review
commit 7b851d9af2
2 changed files with 111 additions and 1 deletions

View File

@ -18,6 +18,7 @@ import (
"fmt"
"strings"
"k8s.io/apimachinery/pkg/labels"
"sigs.k8s.io/kustomize/kyaml/kio"
"sigs.k8s.io/kustomize/kyaml/kio/filters"
"sigs.k8s.io/kustomize/kyaml/yaml"
@ -84,6 +85,17 @@ func (f DocumentSelector) ByNamespace(ns string) DocumentSelector {
return f
}
// ByLabel adds filter to filter by labelSelector.
// For more details about syntax for labelSelector refer to Parse() function description from
// https://github.com/kubernetes/apimachinery/blob/master/pkg/labels/selector.go
func (f DocumentSelector) ByLabel(labelSelector string) DocumentSelector {
if labelSelector != "" {
f.filters = append(f.filters, &LabelFilter{MatchExpression: labelSelector})
return f
}
return f
}
// Filter RNode objects
func (f DocumentSelector) Filter(items []*yaml.RNode) (result []*yaml.RNode, err error) {
result = items
@ -95,3 +107,35 @@ func (f DocumentSelector) Filter(items []*yaml.RNode) (result []*yaml.RNode, err
}
return result, nil
}
var _ kio.Filter = &LabelFilter{}
// LabelFilter allows to filter labels based on label Selectors
// Uses kubernetes label selector library from apimachinery package undreneath
// For syntax for MatchExpression, please refer to description of Parse() function at
// https://github.com/kubernetes/apimachinery/blob/master/pkg/labels/selector.go
type LabelFilter struct {
MatchExpression string
}
// Filter implements RNode filter interface
func (lf *LabelFilter) Filter(input []*yaml.RNode) ([]*yaml.RNode, error) {
var output kio.ResourceNodeSlice
selector, err := labels.Parse(lf.MatchExpression)
if err != nil {
return nil, err
}
for _, node := range input {
nodeLabels, err := node.GetLabels()
if err != nil {
return nil, err
}
if selector.Matches(labels.Set(nodeLabels)) {
output = append(output, node)
}
}
return output, nil
}

View File

@ -33,6 +33,8 @@ func documents(t *testing.T) []*yaml.RNode {
apiVersion: v1
kind: Pod
metadata:
labels:
app: pod1
name: p1
namespace: capi
---
@ -69,6 +71,8 @@ func TestFilter(t *testing.T) {
expectedDocs: `apiVersion: v1
kind: Pod
metadata:
labels:
app: pod1
name: p1
namespace: capi`,
},
@ -78,6 +82,8 @@ metadata:
expectedDocs: `apiVersion: v1
kind: Pod
metadata:
labels:
app: pod1
name: p1
namespace: capi
---
@ -114,6 +120,8 @@ metadata:
expectedDocs: `apiVersion: v1
kind: Pod
metadata:
labels:
app: pod1
name: p1
namespace: capi
---
@ -139,12 +147,70 @@ kind: Deployment
metadata:
name: p1`,
},
{
name: "Get by label exact match",
selector: kyamlutils.DocumentSelector{}.ByLabel("app=pod1"),
expectedDocs: `apiVersion: v1
kind: Pod
metadata:
labels:
app: pod1
name: p1
namespace: capi`,
},
{
name: "Get by empty label",
selector: kyamlutils.DocumentSelector{}.ByLabel(""),
expectedDocs: `apiVersion: v1
kind: Pod
metadata:
labels:
app: pod1
name: p1
namespace: capi
---
apiVersion: v1
kind: Pod
metadata:
name: p2
namespace: capi
---
apiVersion: v1beta1
kind: Deployment
metadata:
name: p1`,
},
{
name: "Get by label not equal",
selector: kyamlutils.DocumentSelector{}.ByLabel("app!=pod1"),
expectedDocs: `apiVersion: v1
kind: Pod
metadata:
name: p2
namespace: capi
---
apiVersion: v1beta1
kind: Deployment
metadata:
name: p1`,
},
{
name: "Get by label inclusion",
selector: kyamlutils.DocumentSelector{}.ByLabel("app in (pod1)"),
expectedDocs: `apiVersion: v1
kind: Pod
metadata:
labels:
app: pod1
name: p1
namespace: capi`,
},
}
for _, tc := range testCases {
tc := tc
t.Run(tc.name, func(t *testing.T) {
filteredDocs, err := tc.selector.Filter(docs)
assert.Equal(t, err, tc.expectedErr)
assert.Equal(t, tc.expectedErr, err)
buf := &bytes.Buffer{}
err = kio.ByteWriter{Writer: buf}.Write(filteredDocs)