Merge "[#11] Implement selector kustomize primitive"

This commit is contained in:
Zuul 2020-03-04 19:24:57 +00:00 committed by Gerrit Code Review
commit 7f06e556a4
6 changed files with 122 additions and 39 deletions

View File

@ -2,7 +2,6 @@ package initinfra
import (
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/types"
"opendev.org/airship/airshipctl/pkg/config"
"opendev.org/airship/airshipctl/pkg/document"
@ -71,15 +70,19 @@ func (infra *Infra) Deploy() error {
return err
}
filterSelector := types.Selector{
LabelSelector: document.EphemeralClusterSelector,
}
ls := document.EphemeralClusterSelector
selector := document.NewSelector().ByLabel(ls)
// Get documents that are annotated to belong to initinfra
docs, err := b.Select(filterSelector)
docs, err := b.Select(selector)
if err != nil {
return err
}
if len(docs) == 0 {
return document.ErrDocNotFound{
Selector: ls,
}
}
// Label every document indicating that it was deployed by initinfra module for further reference
// This may be used later to get all resources that are part of initinfra module, for monitoring, alerting

View File

@ -8,13 +8,11 @@ import (
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer"
"sigs.k8s.io/kustomize/v3/k8sdeps/validator"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
"sigs.k8s.io/kustomize/v3/pkg/loader"
"sigs.k8s.io/kustomize/v3/pkg/plugins"
"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"
@ -51,11 +49,11 @@ type Bundle interface {
SetKustomizeBuildOptions(KustomizeBuildOptions) error
SetFileSystem(fs.FileSystem) error
GetFileSystem() fs.FileSystem
Select(selector types.Selector) ([]Document, error)
Select(selector Selector) ([]Document, error)
GetByGvk(string, string, string) ([]Document, error)
GetByName(string) (Document, error)
GetByAnnotation(string) ([]Document, error)
GetByLabel(string) ([]Document, error)
GetByAnnotation(annotationSelector string) ([]Document, error)
GetByLabel(labelSelector string) ([]Document, error)
GetAllDocuments() ([]Document, error)
}
@ -188,11 +186,11 @@ func (b *BundleFactory) GetByName(name string) (Document, error) {
}
}
// Select offers a direct interface to pass a Kustomize Selector to the bundle
// returning Documents that match the criteria
func (b *BundleFactory) Select(selector types.Selector) ([]Document, error) {
// Select offers an interface to pass a Selector, built on top of kustomize Selector
// to the bundle returning Documents that match the criteria
func (b *BundleFactory) Select(selector Selector) ([]Document, error) {
// use the kustomize select method
resources, err := b.ResMap.Select(selector)
resources, err := b.ResMap.Select(selector.Selector)
if err != nil {
return []Document{}, err
}
@ -211,19 +209,17 @@ func (b *BundleFactory) Select(selector types.Selector) ([]Document, error) {
}
// GetByAnnotation is a convenience method to get documents for a particular annotation
func (b *BundleFactory) GetByAnnotation(annotation string) ([]Document, error) {
func (b *BundleFactory) GetByAnnotation(annotationSelector string) ([]Document, error) {
// Construct kustomize annotation selector
selector := types.Selector{AnnotationSelector: annotation}
selector := NewSelector().ByAnnotation(annotationSelector)
// pass it to the selector
return b.Select(selector)
}
// GetByLabel is a convenience method to get documents for a particular label
func (b *BundleFactory) GetByLabel(label string) ([]Document, error) {
// Construct kustomize annotation selector
selector := types.Selector{LabelSelector: label}
func (b *BundleFactory) GetByLabel(labelSelector string) ([]Document, error) {
// Construct kustomize label selector
selector := NewSelector().ByLabel(labelSelector)
// pass it to the selector
return b.Select(selector)
}
@ -231,10 +227,8 @@ func (b *BundleFactory) GetByLabel(label string) ([]Document, error) {
// GetByGvk is a convenience method to get documents for a particular Gvk tuple
func (b *BundleFactory) GetByGvk(group, version, kind string) ([]Document, error) {
// Construct kustomize gvk object
g := gvk.Gvk{Group: group, Version: version, Kind: kind}
selector := NewSelector().ByGvk(group, version, kind)
// pass it to the selector
selector := types.Selector{Gvk: g}
return b.Select(selector)
}

View File

@ -6,9 +6,8 @@ import (
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
"sigs.k8s.io/kustomize/v3/pkg/types"
"opendev.org/airship/airshipctl/pkg/document"
"opendev.org/airship/airshipctl/testutil"
)
@ -57,8 +56,7 @@ func TestBundleDocumentFiltering(t *testing.T) {
// Select* tests test the Kustomize selector, which requires we build Kustomize
// selector objects which is useful for advanced searches that
// need to stack filters
g := gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
selector := types.Selector{Gvk: g}
selector := document.NewSelector().ByGvk("apps", "v1", "Deployment")
docs, err := bundle.Select(selector)
require.NoError(err, "Error trying to select resources")
@ -67,7 +65,7 @@ func TestBundleDocumentFiltering(t *testing.T) {
t.Run("SelectAnnotations", func(t *testing.T) {
// Find documents with a particular annotation, namely airshipit.org/clustertype=ephemeral
selector := types.Selector{AnnotationSelector: "airshipit.org/clustertype=ephemeral"}
selector := document.NewSelector().ByAnnotation("airshipit.org/clustertype=ephemeral")
docs, err := bundle.Select(selector)
require.NoError(err, "Error trying to select annotated resources")
@ -78,12 +76,48 @@ func TestBundleDocumentFiltering(t *testing.T) {
// Find documents with a particular label, namely app=workflow-controller
// note how this will only find resources labeled at the top most level (metadata.labels)
// and not spec templates with this label (spec.template.metadata.labels)
selector := types.Selector{LabelSelector: "app=workflow-controller"}
selector := document.NewSelector().ByLabel("app=workflow-controller")
docs, err := bundle.Select(selector)
require.NoError(err, "Error trying to select labeled resources")
assert.Len(docs, 1, "SelectLabels returned wrong number of resources")
})
t.Run("SelectByLabelAndName", func(t *testing.T) {
// Find documents with a particular label and name,
// namely app=workflow-controller and name workflow-controller
selector := document.NewSelector().ByName("workflow-controller").ByLabel("app=workflow-controller")
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")
})
t.Run("SelectByTwoLabels", func(t *testing.T) {
// Find documents with two particular label, namely app=workflow-controller arbitrary-label=some-label
selector := document.NewSelector().
ByLabel("app=workflow-controller").
ByLabel("arbitrary-label=some-label")
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.Equal("workflow-controller", docs[0].GetName())
})
t.Run("SelectByTwoAnnotations", func(t *testing.T) {
// Find documents with two particular annotations,
// namely app=workflow-controller and name workflow-controller
selector := document.NewSelector().
ByAnnotation("airshipit.org/clustertype=target").
ByAnnotation("airshipit.org/random-payload=random")
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.Equal("argo-ui", docs[0].GetName())
})
t.Run("Write", func(t *testing.T) {
// Ensure we can write out a bundle
//

53
pkg/document/selectors.go Normal file
View File

@ -0,0 +1,53 @@
package document
import (
"strings"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
// Selector provides abstraction layer in front of kustomize selector
type Selector struct {
types.Selector
}
// NewSelector returns instance of Selector container
func NewSelector() Selector {
return Selector{}
}
// Following set of functions allows to build selector object
// by name, gvk, label selector and annotation selector
// ByName select by name
func (s Selector) ByName(name string) Selector {
s.Name = name
return s
}
// ByGvk select by gvk
func (s Selector) ByGvk(group, version, kind string) Selector {
s.Gvk = gvk.Gvk{Group: group, Version: version, Kind: kind}
return s
}
// ByLabel select by label selector
func (s Selector) ByLabel(labelSelector string) Selector {
if s.LabelSelector != "" {
s.LabelSelector = strings.Join([]string{s.LabelSelector, labelSelector}, ",")
} else {
s.LabelSelector = labelSelector
}
return s
}
// ByAnnotation select by annotation selector.
func (s Selector) ByAnnotation(annotationSelector string) Selector {
if s.AnnotationSelector != "" {
s.AnnotationSelector = strings.Join([]string{s.AnnotationSelector, annotationSelector}, ",")
} else {
s.AnnotationSelector = annotationSelector
}
return s
}

View File

@ -232,6 +232,7 @@ kind: Deployment
metadata:
annotations:
airshipit.org/clustertype: target
airshipit.org/random-payload: random
name: argo-ui
spec:
selector:
@ -266,6 +267,7 @@ metadata:
airshipit.org/clustertype: target
labels:
app: workflow-controller
arbitrary-label: some-label
name: workflow-controller
spec:
selector:

View File

@ -13,8 +13,6 @@ import (
"opendev.org/airship/airshipctl/pkg/remote/redfish"
"sigs.k8s.io/kustomize/v3/pkg/fs"
"sigs.k8s.io/kustomize/v3/pkg/gvk"
"sigs.k8s.io/kustomize/v3/pkg/types"
)
const (
@ -89,18 +87,17 @@ func getRemoteDirectConfig(settings *environment.AirshipCTLSettings) (*config.Re
return nil, "", err
}
label := document.EphemeralClusterSelector
filter := types.Selector{
Gvk: gvk.FromKind(AirshipHostKind),
LabelSelector: label,
}
docs, err := docBundle.Select(filter)
ls := document.EphemeralClusterSelector
selector := document.NewSelector().
ByGvk("", "", AirshipHostKind).
ByLabel(ls)
docs, err := docBundle.Select(selector)
if err != nil {
return nil, "", err
}
if len(docs) == 0 {
return nil, "", document.ErrDocNotFound{
Selector: label,
Selector: ls,
Kind: AirshipHostKind,
}
}