mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-27 16:17:34 +00:00
Fix: add flag --label to filer components and traits (#2217)
Added flag `--flag` to filter when executing `vela componnets` and `vela traits` Fix https://github.com/oam-dev/kubevela.io/pull/222#discussion_r699214816
This commit is contained in:
@@ -162,6 +162,7 @@ type Capability struct {
|
||||
Center string `json:"center,omitempty"`
|
||||
Status string `json:"status,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
Labels map[string]string `json:"labels,omitempty"`
|
||||
Category CapabilityCategory `json:"category,omitempty"`
|
||||
|
||||
// trait only
|
||||
|
||||
@@ -71,3 +71,6 @@ const (
|
||||
// TypePlugin defines one category used in Kubectl Plugin
|
||||
TypePlugin = "Plugin Command"
|
||||
)
|
||||
|
||||
// LabelArg is the argument `label` of a definition
|
||||
const LabelArg = "label"
|
||||
|
||||
@@ -5,6 +5,7 @@ metadata:
|
||||
namespace: {{.Values.systemDefinitionNamespace}}
|
||||
annotations:
|
||||
definition.oam.dev/description: Terraform configuration for Alibaba Cloud ACK cluster
|
||||
labels:
|
||||
type: terraform
|
||||
spec:
|
||||
workload:
|
||||
|
||||
@@ -5,6 +5,7 @@ metadata:
|
||||
namespace: {{.Values.systemDefinitionNamespace}}
|
||||
annotations:
|
||||
definition.oam.dev/description: Terraform configuration for Alibaba Cloud OSS object
|
||||
labels:
|
||||
type: terraform
|
||||
spec:
|
||||
workload:
|
||||
|
||||
@@ -5,6 +5,7 @@ metadata:
|
||||
namespace: {{.Values.systemDefinitionNamespace}}
|
||||
annotations:
|
||||
definition.oam.dev/description: Terraform configuration for Alibaba Cloud RDS object
|
||||
labels:
|
||||
type: terraform
|
||||
spec:
|
||||
workload:
|
||||
|
||||
@@ -17,16 +17,25 @@ limitations under the License.
|
||||
package e2e
|
||||
|
||||
import (
|
||||
"github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"github.com/oam-dev/kubevela/e2e"
|
||||
)
|
||||
|
||||
var _ = ginkgo.Describe("Workload", func() {
|
||||
var _ = Describe("Workload", func() {
|
||||
e2e.WorkloadCapabilityListContext()
|
||||
|
||||
Context("list components with `label` filter", func() {
|
||||
It("list components with the specified label", func() {
|
||||
output, err := e2e.Exec("vela components --label type=terraform")
|
||||
Expect(err).NotTo(HaveOccurred())
|
||||
Expect(output).To(ContainSubstring("alibaba-oss"))
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
var _ = ginkgo.Describe("Test vela show", func() {
|
||||
var _ = Describe("Test vela show", func() {
|
||||
e2e.ShowCapabilityReference("show webservice", "webservice")
|
||||
|
||||
env := "namespace-xxxfwrr23erfm"
|
||||
|
||||
@@ -204,7 +204,7 @@ func NewCapListCommand(c common2.Args, ioStreams cmdutil.IOStreams) *cobra.Comma
|
||||
return err
|
||||
}
|
||||
|
||||
err = printCenterCapabilities(env.Namespace, repoName, c, ioStreams, nil)
|
||||
err = printCenterCapabilities(env.Namespace, repoName, c, ioStreams, nil, "")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -268,7 +268,7 @@ func removeCapCenter(args []string, ioStreams cmdutil.IOStreams) error {
|
||||
}
|
||||
return err
|
||||
}
|
||||
func printCenterCapabilities(namespace, repoName string, args common2.Args, ioStreams cmdutil.IOStreams, option *types.CapType) error {
|
||||
func printCenterCapabilities(namespace, repoName string, args common2.Args, ioStreams cmdutil.IOStreams, option *types.CapType, label string) error {
|
||||
capabilityList, err := common.ListCapabilities(namespace, args, repoName)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -277,6 +277,9 @@ func printCenterCapabilities(namespace, repoName string, args common2.Args, ioSt
|
||||
table.AddRow("NAME", "CENTER", "TYPE", "DEFINITION", "STATUS", "APPLIES-TO")
|
||||
|
||||
for _, c := range capabilityList {
|
||||
if label != "" && !common.CheckLabelExistence(c.Labels, label) {
|
||||
continue
|
||||
}
|
||||
if option == nil {
|
||||
table.AddRow(c.Name, c.Center, c.Type, c.CrdName, c.Status, c.AppliesTo)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package cli
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -54,11 +55,20 @@ func NewComponentsCommand(c common2.Args, ioStreams cmdutil.IOStreams) *cobra.Co
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
label, err := cmd.Flags().GetString(types.LabelArg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if label != "" && len(strings.Split(label, "=")) != 2 {
|
||||
return fmt.Errorf("label %s is not in the right format", label)
|
||||
}
|
||||
|
||||
if !isDiscover {
|
||||
return printComponentList(env.Namespace, c, ioStreams)
|
||||
return printComponentList(env.Namespace, c, ioStreams, label)
|
||||
}
|
||||
option := types.TypeComponentDefinition
|
||||
err = printCenterCapabilities(env.Namespace, "", c, ioStreams, &option)
|
||||
err = printCenterCapabilities(env.Namespace, "", c, ioStreams, &option, label)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -70,11 +80,12 @@ func NewComponentsCommand(c common2.Args, ioStreams cmdutil.IOStreams) *cobra.Co
|
||||
},
|
||||
}
|
||||
cmd.Flags().Bool("discover", false, "discover traits in capability centers")
|
||||
cmd.Flags().String(types.LabelArg, "", "a label to filter components, the format is `--label type=terraform`")
|
||||
cmd.SetOut(ioStreams.Out)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func printComponentList(userNamespace string, c common2.Args, ioStreams cmdutil.IOStreams) error {
|
||||
func printComponentList(userNamespace string, c common2.Args, ioStreams cmdutil.IOStreams, label string) error {
|
||||
def, err := common.ListRawComponentDefinitions(userNamespace, c)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -89,6 +100,9 @@ func printComponentList(userNamespace string, c common2.Args, ioStreams cmdutil.
|
||||
table.AddRow("NAME", "NAMESPACE", "WORKLOAD", "DESCRIPTION")
|
||||
|
||||
for _, r := range def {
|
||||
if label != "" && !common.CheckLabelExistence(r.Labels, label) {
|
||||
continue
|
||||
}
|
||||
var workload string
|
||||
if r.Spec.Workload.Type != "" {
|
||||
workload = r.Spec.Workload.Type
|
||||
|
||||
@@ -54,11 +54,19 @@ func NewTraitsCommand(c common2.Args, ioStreams cmdutil.IOStreams) *cobra.Comman
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
label, err := cmd.Flags().GetString(types.LabelArg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if label != "" && len(strings.Split(label, "=")) != 2 {
|
||||
return fmt.Errorf("label %s is not in the right format", label)
|
||||
|
||||
}
|
||||
if !isDiscover {
|
||||
return printTraitList(env.Namespace, c, ioStreams)
|
||||
return printTraitList(env.Namespace, c, ioStreams, label)
|
||||
}
|
||||
option := types.TypeTrait
|
||||
err = printCenterCapabilities(env.Namespace, "", c, ioStreams, &option)
|
||||
err = printCenterCapabilities(env.Namespace, "", c, ioStreams, &option, label)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -70,11 +78,12 @@ func NewTraitsCommand(c common2.Args, ioStreams cmdutil.IOStreams) *cobra.Comman
|
||||
},
|
||||
}
|
||||
cmd.Flags().Bool("discover", false, "discover traits in capability centers")
|
||||
cmd.Flags().String(types.LabelArg, "", "a label to filter components, the format is `--label type=terraform`")
|
||||
cmd.SetOut(ioStreams.Out)
|
||||
return cmd
|
||||
}
|
||||
|
||||
func printTraitList(userNamespace string, c common2.Args, ioStreams cmdutil.IOStreams) error {
|
||||
func printTraitList(userNamespace string, c common2.Args, ioStreams cmdutil.IOStreams, label string) error {
|
||||
table := newUITable()
|
||||
table.Wrap = true
|
||||
|
||||
@@ -84,6 +93,9 @@ func printTraitList(userNamespace string, c common2.Args, ioStreams cmdutil.IOSt
|
||||
}
|
||||
table.AddRow("NAME", "NAMESPACE", "APPLIES-TO", "CONFLICTS-WITH", "POD-DISRUPTIVE", "DESCRIPTION")
|
||||
for _, t := range traitDefinitionList {
|
||||
if label != "" && !common.CheckLabelExistence(t.Labels, label) {
|
||||
continue
|
||||
}
|
||||
table.AddRow(t.Name, t.Namespace, strings.Join(t.Spec.AppliesToWorkloads, ","), strings.Join(t.Spec.ConflictsWith, ","), t.Spec.PodDisruptive, plugins.GetDescription(t.Annotations))
|
||||
}
|
||||
ioStreams.Info(table.String())
|
||||
|
||||
@@ -504,3 +504,15 @@ func GetCapabilityConfigMap(kubeClient client.Client, capabilityName string) (co
|
||||
err := kubeClient.Get(context.Background(), client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: cmName}, &cm)
|
||||
return cm, err
|
||||
}
|
||||
|
||||
// CheckLabelExistence checks whether a label `key=value` exists in definition labels
|
||||
func CheckLabelExistence(labels map[string]string, label string) bool {
|
||||
splitLabel := strings.Split(label, "=")
|
||||
k, v := splitLabel[0], splitLabel[1]
|
||||
if labelValue, ok := labels[k]; ok {
|
||||
if labelValue == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import (
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
|
||||
"github.com/oam-dev/kubevela/apis/types"
|
||||
@@ -51,3 +52,41 @@ func TestAddSourceIntoDefinition(t *testing.T) {
|
||||
t.Errorf("error result want %s, got %s", result, testcase)
|
||||
}
|
||||
}
|
||||
|
||||
func TestCheckLabelExistence(t *testing.T) {
|
||||
cases := map[string]struct {
|
||||
labels map[string]string
|
||||
label string
|
||||
existed bool
|
||||
}{
|
||||
"label exists": {
|
||||
labels: map[string]string{
|
||||
"env": "prod",
|
||||
},
|
||||
label: "env=prod",
|
||||
existed: true,
|
||||
},
|
||||
|
||||
"label's key matches": {
|
||||
labels: map[string]string{
|
||||
"env": "prod",
|
||||
},
|
||||
label: "env=dev",
|
||||
existed: false,
|
||||
},
|
||||
"label's key doesn't match": {
|
||||
labels: map[string]string{
|
||||
"env": "prod",
|
||||
},
|
||||
label: "type=terraform",
|
||||
existed: false,
|
||||
},
|
||||
}
|
||||
|
||||
for name, tc := range cases {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
result := CheckLabelExistence(tc.labels, tc.label)
|
||||
assert.Equal(t, result, tc.existed)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -245,14 +245,14 @@ func ParseCapability(mapper discoverymapper.DiscoveryMapper, data []byte) (types
|
||||
if err != nil {
|
||||
return types.Capability{}, err
|
||||
}
|
||||
return HandleDefinition(cd.Name, ref.Name, cd.Annotations, cd.Spec.Extension, types.TypeComponentDefinition, nil, cd.Spec.Schematic)
|
||||
return HandleDefinition(cd.Name, ref.Name, cd.Annotations, cd.Labels, cd.Spec.Extension, types.TypeComponentDefinition, nil, cd.Spec.Schematic)
|
||||
case "TraitDefinition":
|
||||
var td v1beta1.TraitDefinition
|
||||
err = yaml.Unmarshal(data, &td)
|
||||
if err != nil {
|
||||
return types.Capability{}, err
|
||||
}
|
||||
return HandleDefinition(td.Name, td.Spec.Reference.Name, td.Annotations, td.Spec.Extension, types.TypeTrait, td.Spec.AppliesToWorkloads, td.Spec.Schematic)
|
||||
return HandleDefinition(td.Name, td.Spec.Reference.Name, td.Annotations, td.Labels, td.Spec.Extension, types.TypeTrait, td.Spec.AppliesToWorkloads, td.Spec.Schematic)
|
||||
case "ScopeDefinition":
|
||||
// TODO(wonderflow): support scope definition here.
|
||||
}
|
||||
|
||||
@@ -205,7 +205,8 @@ func validateCapabilities(tmp *types.Capability, dm discoverymapper.DiscoveryMap
|
||||
}
|
||||
|
||||
// HandleDefinition will handle definition to capability
|
||||
func HandleDefinition(name, crdName string, annotation map[string]string, extension *runtime.RawExtension, tp types.CapType, applyTo []string, schematic *commontypes.Schematic) (types.Capability, error) {
|
||||
func HandleDefinition(name, crdName string, annotation, labels map[string]string, extension *runtime.RawExtension, tp types.CapType,
|
||||
applyTo []string, schematic *commontypes.Schematic) (types.Capability, error) {
|
||||
var tmp types.Capability
|
||||
tmp, err := HandleTemplate(extension, schematic, name)
|
||||
if err != nil {
|
||||
@@ -217,6 +218,7 @@ func HandleDefinition(name, crdName string, annotation map[string]string, extens
|
||||
}
|
||||
tmp.CrdName = crdName
|
||||
tmp.Description = GetDescription(annotation)
|
||||
tmp.Labels = labels
|
||||
return tmp, nil
|
||||
}
|
||||
|
||||
@@ -352,8 +354,8 @@ func GetCapabilityByName(ctx context.Context, c common.Args, capabilityName stri
|
||||
|
||||
// GetCapabilityByComponentDefinitionObject gets capability by ComponentDefinition object
|
||||
func GetCapabilityByComponentDefinitionObject(componentDef v1beta1.ComponentDefinition, referenceName string) (*types.Capability, error) {
|
||||
capability, err := HandleDefinition(componentDef.Name, referenceName,
|
||||
componentDef.Annotations, componentDef.Spec.Extension, types.TypeComponentDefinition, nil, componentDef.Spec.Schematic)
|
||||
capability, err := HandleDefinition(componentDef.Name, referenceName, componentDef.Annotations, componentDef.Labels,
|
||||
componentDef.Spec.Extension, types.TypeComponentDefinition, nil, componentDef.Spec.Schematic)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to handle ComponentDefinition")
|
||||
}
|
||||
@@ -367,8 +369,8 @@ func GetCapabilityByTraitDefinitionObject(traitDef v1beta1.TraitDefinition) (*ty
|
||||
capability types.Capability
|
||||
err error
|
||||
)
|
||||
capability, err = HandleDefinition(traitDef.Name, traitDef.Spec.Reference.Name,
|
||||
traitDef.Annotations, traitDef.Spec.Extension, types.TypeTrait, nil, traitDef.Spec.Schematic)
|
||||
capability, err = HandleDefinition(traitDef.Name, traitDef.Spec.Reference.Name, traitDef.Annotations, traitDef.Labels,
|
||||
traitDef.Spec.Extension, types.TypeTrait, nil, traitDef.Spec.Schematic)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "failed to handle TraitDefinition")
|
||||
}
|
||||
|
||||
@@ -79,6 +79,7 @@ var _ = Describe("DefinitionFiles", func() {
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Labels: map[string]string{"usecase": "forplugintest"},
|
||||
}
|
||||
|
||||
websvc := types.Capability{
|
||||
@@ -108,6 +109,7 @@ var _ = Describe("DefinitionFiles", func() {
|
||||
APIVersion: "apps/v1",
|
||||
Kind: "Deployment",
|
||||
},
|
||||
Labels: map[string]string{"usecase": "forplugintest"},
|
||||
}
|
||||
|
||||
req, _ := labels.NewRequirement("usecase", selection.Equals, []string{"forplugintest"})
|
||||
|
||||
Reference in New Issue
Block a user