Merge "[#11] Implement selector kustomize primitive"
This commit is contained in:
commit
7f06e556a4
@ -2,7 +2,6 @@ package initinfra
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
"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/config"
|
||||||
"opendev.org/airship/airshipctl/pkg/document"
|
"opendev.org/airship/airshipctl/pkg/document"
|
||||||
@ -71,15 +70,19 @@ func (infra *Infra) Deploy() error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
filterSelector := types.Selector{
|
ls := document.EphemeralClusterSelector
|
||||||
LabelSelector: document.EphemeralClusterSelector,
|
selector := document.NewSelector().ByLabel(ls)
|
||||||
}
|
|
||||||
|
|
||||||
// Get documents that are annotated to belong to initinfra
|
// Get documents that are annotated to belong to initinfra
|
||||||
docs, err := b.Select(filterSelector)
|
docs, err := b.Select(selector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
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
|
// 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
|
// This may be used later to get all resources that are part of initinfra module, for monitoring, alerting
|
||||||
|
@ -8,13 +8,11 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer"
|
"sigs.k8s.io/kustomize/v3/k8sdeps/transformer"
|
||||||
"sigs.k8s.io/kustomize/v3/k8sdeps/validator"
|
"sigs.k8s.io/kustomize/v3/k8sdeps/validator"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
"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/loader"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
"sigs.k8s.io/kustomize/v3/pkg/plugins"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
"sigs.k8s.io/kustomize/v3/pkg/resmap"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
"sigs.k8s.io/kustomize/v3/pkg/resource"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/target"
|
"sigs.k8s.io/kustomize/v3/pkg/target"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
|
||||||
|
|
||||||
docplugins "opendev.org/airship/airshipctl/pkg/document/plugins"
|
docplugins "opendev.org/airship/airshipctl/pkg/document/plugins"
|
||||||
"opendev.org/airship/airshipctl/pkg/log"
|
"opendev.org/airship/airshipctl/pkg/log"
|
||||||
@ -51,11 +49,11 @@ type Bundle interface {
|
|||||||
SetKustomizeBuildOptions(KustomizeBuildOptions) error
|
SetKustomizeBuildOptions(KustomizeBuildOptions) error
|
||||||
SetFileSystem(fs.FileSystem) error
|
SetFileSystem(fs.FileSystem) error
|
||||||
GetFileSystem() fs.FileSystem
|
GetFileSystem() fs.FileSystem
|
||||||
Select(selector types.Selector) ([]Document, error)
|
Select(selector Selector) ([]Document, error)
|
||||||
GetByGvk(string, string, string) ([]Document, error)
|
GetByGvk(string, string, string) ([]Document, error)
|
||||||
GetByName(string) (Document, error)
|
GetByName(string) (Document, error)
|
||||||
GetByAnnotation(string) ([]Document, error)
|
GetByAnnotation(annotationSelector string) ([]Document, error)
|
||||||
GetByLabel(string) ([]Document, error)
|
GetByLabel(labelSelector string) ([]Document, error)
|
||||||
GetAllDocuments() ([]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
|
// Select offers an interface to pass a Selector, built on top of kustomize Selector
|
||||||
// returning Documents that match the criteria
|
// to the bundle returning Documents that match the criteria
|
||||||
func (b *BundleFactory) Select(selector types.Selector) ([]Document, error) {
|
func (b *BundleFactory) Select(selector Selector) ([]Document, error) {
|
||||||
// use the kustomize select method
|
// use the kustomize select method
|
||||||
resources, err := b.ResMap.Select(selector)
|
resources, err := b.ResMap.Select(selector.Selector)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return []Document{}, err
|
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
|
// 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
|
// Construct kustomize annotation selector
|
||||||
selector := types.Selector{AnnotationSelector: annotation}
|
selector := NewSelector().ByAnnotation(annotationSelector)
|
||||||
|
|
||||||
// pass it to the selector
|
// pass it to the selector
|
||||||
return b.Select(selector)
|
return b.Select(selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetByLabel is a convenience method to get documents for a particular label
|
// GetByLabel is a convenience method to get documents for a particular label
|
||||||
func (b *BundleFactory) GetByLabel(label string) ([]Document, error) {
|
func (b *BundleFactory) GetByLabel(labelSelector string) ([]Document, error) {
|
||||||
// Construct kustomize annotation selector
|
// Construct kustomize label selector
|
||||||
selector := types.Selector{LabelSelector: label}
|
selector := NewSelector().ByLabel(labelSelector)
|
||||||
|
|
||||||
// pass it to the selector
|
// pass it to the selector
|
||||||
return b.Select(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
|
// GetByGvk is a convenience method to get documents for a particular Gvk tuple
|
||||||
func (b *BundleFactory) GetByGvk(group, version, kind string) ([]Document, error) {
|
func (b *BundleFactory) GetByGvk(group, version, kind string) ([]Document, error) {
|
||||||
// Construct kustomize gvk object
|
// Construct kustomize gvk object
|
||||||
g := gvk.Gvk{Group: group, Version: version, Kind: kind}
|
selector := NewSelector().ByGvk(group, version, kind)
|
||||||
|
|
||||||
// pass it to the selector
|
// pass it to the selector
|
||||||
selector := types.Selector{Gvk: g}
|
|
||||||
return b.Select(selector)
|
return b.Select(selector)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6,9 +6,8 @@ import (
|
|||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/stretchr/testify/require"
|
"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"
|
"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
|
// Select* tests test the Kustomize selector, which requires we build Kustomize
|
||||||
// selector objects which is useful for advanced searches that
|
// selector objects which is useful for advanced searches that
|
||||||
// need to stack filters
|
// need to stack filters
|
||||||
g := gvk.Gvk{Group: "apps", Version: "v1", Kind: "Deployment"}
|
selector := document.NewSelector().ByGvk("apps", "v1", "Deployment")
|
||||||
selector := types.Selector{Gvk: g}
|
|
||||||
docs, err := bundle.Select(selector)
|
docs, err := bundle.Select(selector)
|
||||||
require.NoError(err, "Error trying to select resources")
|
require.NoError(err, "Error trying to select resources")
|
||||||
|
|
||||||
@ -67,7 +65,7 @@ func TestBundleDocumentFiltering(t *testing.T) {
|
|||||||
|
|
||||||
t.Run("SelectAnnotations", func(t *testing.T) {
|
t.Run("SelectAnnotations", func(t *testing.T) {
|
||||||
// Find documents with a particular annotation, namely airshipit.org/clustertype=ephemeral
|
// 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)
|
docs, err := bundle.Select(selector)
|
||||||
require.NoError(err, "Error trying to select annotated resources")
|
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
|
// 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)
|
// 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)
|
// 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)
|
docs, err := bundle.Select(selector)
|
||||||
require.NoError(err, "Error trying to select labeled resources")
|
require.NoError(err, "Error trying to select labeled resources")
|
||||||
|
|
||||||
assert.Len(docs, 1, "SelectLabels returned wrong number of 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) {
|
t.Run("Write", func(t *testing.T) {
|
||||||
// Ensure we can write out a bundle
|
// Ensure we can write out a bundle
|
||||||
//
|
//
|
||||||
|
53
pkg/document/selectors.go
Normal file
53
pkg/document/selectors.go
Normal 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
|
||||||
|
}
|
2
pkg/document/testdata/argo.yaml
vendored
2
pkg/document/testdata/argo.yaml
vendored
@ -232,6 +232,7 @@ kind: Deployment
|
|||||||
metadata:
|
metadata:
|
||||||
annotations:
|
annotations:
|
||||||
airshipit.org/clustertype: target
|
airshipit.org/clustertype: target
|
||||||
|
airshipit.org/random-payload: random
|
||||||
name: argo-ui
|
name: argo-ui
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
@ -266,6 +267,7 @@ metadata:
|
|||||||
airshipit.org/clustertype: target
|
airshipit.org/clustertype: target
|
||||||
labels:
|
labels:
|
||||||
app: workflow-controller
|
app: workflow-controller
|
||||||
|
arbitrary-label: some-label
|
||||||
name: workflow-controller
|
name: workflow-controller
|
||||||
spec:
|
spec:
|
||||||
selector:
|
selector:
|
||||||
|
@ -13,8 +13,6 @@ import (
|
|||||||
"opendev.org/airship/airshipctl/pkg/remote/redfish"
|
"opendev.org/airship/airshipctl/pkg/remote/redfish"
|
||||||
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
"sigs.k8s.io/kustomize/v3/pkg/fs"
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/gvk"
|
|
||||||
"sigs.k8s.io/kustomize/v3/pkg/types"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@ -89,18 +87,17 @@ func getRemoteDirectConfig(settings *environment.AirshipCTLSettings) (*config.Re
|
|||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
label := document.EphemeralClusterSelector
|
ls := document.EphemeralClusterSelector
|
||||||
filter := types.Selector{
|
selector := document.NewSelector().
|
||||||
Gvk: gvk.FromKind(AirshipHostKind),
|
ByGvk("", "", AirshipHostKind).
|
||||||
LabelSelector: label,
|
ByLabel(ls)
|
||||||
}
|
docs, err := docBundle.Select(selector)
|
||||||
docs, err := docBundle.Select(filter)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, "", err
|
return nil, "", err
|
||||||
}
|
}
|
||||||
if len(docs) == 0 {
|
if len(docs) == 0 {
|
||||||
return nil, "", document.ErrDocNotFound{
|
return nil, "", document.ErrDocNotFound{
|
||||||
Selector: label,
|
Selector: ls,
|
||||||
Kind: AirshipHostKind,
|
Kind: AirshipHostKind,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user