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:
Zheng Xi Zhou
2021-09-02 20:51:34 +08:00
committed by GitHub
parent e59374bb7d
commit ecef32a7f3
14 changed files with 118 additions and 18 deletions
+1
View File
@@ -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
+3
View File
@@ -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:
+12 -3
View File
@@ -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"
+5 -2
View File
@@ -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)
}
+17 -3
View File
@@ -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
+15 -3
View File
@@ -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())
+12
View File
@@ -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
}
+39
View File
@@ -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)
})
}
}
+2 -2
View File
@@ -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.
}
+7 -5
View File
@@ -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")
}
+2
View File
@@ -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"})