Merge "Add filtering method for document bundle"
This commit is contained in:
commit
14f52863e0
@ -1,6 +1,7 @@
|
||||
package document
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
@ -12,6 +13,7 @@ import (
|
||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
||||
"sigs.k8s.io/kustomize/v3/pkg/target"
|
||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
||||
|
||||
docplugins "opendev.org/airship/airshipctl/pkg/document/plugins"
|
||||
"opendev.org/airship/airshipctl/pkg/log"
|
||||
@ -46,6 +48,7 @@ type Bundle interface {
|
||||
GetFileSystem() FileSystem
|
||||
Select(selector Selector) ([]Document, error)
|
||||
SelectBundle(selector Selector) (Bundle, error)
|
||||
SelectByFieldValue(string, func(interface{}) bool) (Bundle, error)
|
||||
GetByGvk(string, string, string) ([]Document, error)
|
||||
GetByName(string) (Document, error)
|
||||
GetByAnnotation(annotationSelector string) ([]Document, error)
|
||||
@ -241,6 +244,89 @@ func (b *BundleFactory) SelectBundle(selector Selector) (Bundle, error) {
|
||||
}, nil
|
||||
}
|
||||
|
||||
// SelectByFieldValue returns new Bundle with filtered resource documents.
|
||||
// Method iterates over all resources in the bundle. If resource has field
|
||||
// (i.e. key) specified in JSON path, and the comparison function returns
|
||||
// 'true' for value referenced by JSON path, then resource is added to
|
||||
// resulting bundle.
|
||||
// Example:
|
||||
// The bundle contains 3 documents
|
||||
//
|
||||
// ---
|
||||
// apiVersion: v1
|
||||
// kind: DocKind1
|
||||
// metadata:
|
||||
// name: doc1
|
||||
// spec:
|
||||
// somekey:
|
||||
// somefield: "someValue"
|
||||
// ---
|
||||
// apiVersion: v1
|
||||
// kind: DocKind2
|
||||
// metadata:
|
||||
// name: doc2
|
||||
// spec:
|
||||
// somekey:
|
||||
// somefield: "someValue"
|
||||
// ---
|
||||
// apiVersion: v1
|
||||
// kind: DocKind1
|
||||
// metadata:
|
||||
// name: doc3
|
||||
// spec:
|
||||
// somekey:
|
||||
// somefield: "someOtherValue"
|
||||
//
|
||||
// Execution of bundleInstance.SelectByFieldValue(
|
||||
// "spec.somekey.somefield",
|
||||
// func(v interface{}) { return v == "someValue" })
|
||||
// will return a new Bundle instance containing 2 documents:
|
||||
// ---
|
||||
// apiVersion: v1
|
||||
// kind: DocKind1
|
||||
// metadata:
|
||||
// name: doc1
|
||||
// spec:
|
||||
// somekey:
|
||||
// somefield: "someValue"
|
||||
// ---
|
||||
// apiVersion: v1
|
||||
// kind: DocKind2
|
||||
// metadata:
|
||||
// name: doc2
|
||||
// spec:
|
||||
// somekey:
|
||||
// somefield: "someValue"
|
||||
func (b *BundleFactory) SelectByFieldValue(path string, condition func(interface{}) bool) (Bundle, error) {
|
||||
result := &BundleFactory{
|
||||
KustomizeBuildOptions: b.KustomizeBuildOptions,
|
||||
FileSystem: b.FileSystem,
|
||||
}
|
||||
resourceMap := resmap.New()
|
||||
for _, res := range b.Resources() {
|
||||
val, err := res.GetFieldValue(path)
|
||||
if err != nil {
|
||||
if errors.As(err, &types.NoFieldError{}) {
|
||||
// this resource doesn't have the specified field - skip it
|
||||
continue
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
if condition(val) {
|
||||
if err = resourceMap.Append(res); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if err := result.SetKustomizeResourceMap(resourceMap); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result, nil
|
||||
}
|
||||
|
||||
// GetByAnnotation is a convenience method to get documents for a particular annotation
|
||||
func (b *BundleFactory) GetByAnnotation(annotationSelector string) ([]Document, error) {
|
||||
// Construct kustomize annotation selector
|
||||
|
@ -28,21 +28,21 @@ func TestBundleDocumentFiltering(t *testing.T) {
|
||||
docs, err := bundle.GetByGvk("apps", "v1", "Deployment")
|
||||
require.NoError(err)
|
||||
|
||||
assert.Len(docs, 3, "GetGvk returned the wrong number of resources")
|
||||
assert.Len(docs, 3)
|
||||
})
|
||||
|
||||
t.Run("GetByAnnotation", func(t *testing.T) {
|
||||
docs, err := bundle.GetByAnnotation("airshipit.org/clustertype=ephemeral")
|
||||
require.NoError(err, "Error trying to GetByAnnotation")
|
||||
|
||||
assert.Len(docs, 4, "GetByAnnotation returned wrong number of resources")
|
||||
assert.Len(docs, 4)
|
||||
})
|
||||
|
||||
t.Run("GetByLabel", func(t *testing.T) {
|
||||
docs, err := bundle.GetByLabel("app=workflow-controller")
|
||||
require.NoError(err, "Error trying to GetByLabel")
|
||||
|
||||
assert.Len(docs, 1, "GetByLabel returned wrong number of resources")
|
||||
assert.Len(docs, 1)
|
||||
})
|
||||
|
||||
t.Run("SelectGvk", func(t *testing.T) {
|
||||
@ -53,7 +53,7 @@ func TestBundleDocumentFiltering(t *testing.T) {
|
||||
docs, err := bundle.Select(selector)
|
||||
require.NoError(err, "Error trying to select resources")
|
||||
|
||||
assert.Len(docs, 3, "SelectGvk returned wrong number of resources")
|
||||
assert.Len(docs, 3)
|
||||
})
|
||||
|
||||
t.Run("SelectAnnotations", func(t *testing.T) {
|
||||
@ -62,7 +62,7 @@ func TestBundleDocumentFiltering(t *testing.T) {
|
||||
docs, err := bundle.Select(selector)
|
||||
require.NoError(err, "Error trying to select annotated resources")
|
||||
|
||||
assert.Len(docs, 4, "SelectAnnotations returned wrong number of resources")
|
||||
assert.Len(docs, 4)
|
||||
})
|
||||
|
||||
t.Run("SelectLabels", func(t *testing.T) {
|
||||
@ -73,7 +73,7 @@ func TestBundleDocumentFiltering(t *testing.T) {
|
||||
docs, err := bundle.Select(selector)
|
||||
require.NoError(err, "Error trying to select labeled resources")
|
||||
|
||||
assert.Len(docs, 1, "SelectLabels returned wrong number of resources")
|
||||
assert.Len(docs, 1)
|
||||
})
|
||||
|
||||
t.Run("SelectByLabelAndName", func(t *testing.T) {
|
||||
@ -83,7 +83,7 @@ func TestBundleDocumentFiltering(t *testing.T) {
|
||||
docs, err := bundle.Select(selector)
|
||||
require.NoError(err, "Error trying to select labeled with name resources")
|
||||
|
||||
assert.Len(docs, 1, "SelectByLabelAndName returned wrong number of resources")
|
||||
assert.Len(docs, 1)
|
||||
})
|
||||
|
||||
t.Run("SelectByTwoLabels", func(t *testing.T) {
|
||||
@ -94,7 +94,7 @@ func TestBundleDocumentFiltering(t *testing.T) {
|
||||
docs, err := bundle.Select(selector)
|
||||
require.NoError(err, "Error trying to select by two labels")
|
||||
|
||||
assert.Len(docs, 1, "SelectByTwoLabels returned wrong number of resources")
|
||||
assert.Len(docs, 1)
|
||||
assert.Equal("workflow-controller", docs[0].GetName())
|
||||
})
|
||||
|
||||
@ -107,10 +107,22 @@ func TestBundleDocumentFiltering(t *testing.T) {
|
||||
docs, err := bundle.Select(selector)
|
||||
require.NoError(err, "Error trying to select by two annotations")
|
||||
|
||||
assert.Len(docs, 1, "SelectByTwoAnnotations returned wrong number of resources")
|
||||
assert.Len(docs, 1)
|
||||
assert.Equal("argo-ui", docs[0].GetName())
|
||||
})
|
||||
|
||||
t.Run("SelectByFieldValue", func(t *testing.T) {
|
||||
// Find documents with a particular value referenced by JSON path
|
||||
filter := func(val interface{}) bool { return val == "01:3b:8b:0c:ec:8b" }
|
||||
filteredBundle, err := bundle.SelectByFieldValue("spec.bootMACAddress", filter)
|
||||
require.NoError(err, "Error trying to filter resources")
|
||||
docs, err := filteredBundle.GetAllDocuments()
|
||||
require.NoError(err)
|
||||
assert.Len(docs, 1)
|
||||
assert.Equal(docs[0].GetKind(), "BareMetalHost")
|
||||
assert.Equal(docs[0].GetName(), "master-1")
|
||||
})
|
||||
|
||||
t.Run("Write", func(t *testing.T) {
|
||||
// Ensure we can write out a bundle
|
||||
//
|
||||
|
Loading…
x
Reference in New Issue
Block a user