github.com/oam-dev/kubevela@v1.9.11/references/docgen/cluster.go (about)

     1  /*
     2  Copyright 2021 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package docgen
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"strings"
    23  
    24  	"github.com/pkg/errors"
    25  	kerrors "k8s.io/apimachinery/pkg/api/errors"
    26  	"k8s.io/apimachinery/pkg/api/meta"
    27  	"k8s.io/apimachinery/pkg/labels"
    28  	"k8s.io/apimachinery/pkg/runtime"
    29  	"k8s.io/klog/v2"
    30  	"sigs.k8s.io/controller-runtime/pkg/client"
    31  
    32  	"github.com/kubevela/workflow/pkg/cue/packages"
    33  
    34  	commontypes "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
    35  	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
    36  	"github.com/oam-dev/kubevela/apis/types"
    37  	"github.com/oam-dev/kubevela/pkg/appfile"
    38  	"github.com/oam-dev/kubevela/pkg/cue"
    39  	"github.com/oam-dev/kubevela/pkg/definition"
    40  	"github.com/oam-dev/kubevela/pkg/oam/util"
    41  	"github.com/oam-dev/kubevela/pkg/utils"
    42  	"github.com/oam-dev/kubevela/pkg/utils/common"
    43  	"github.com/oam-dev/kubevela/references/docgen/fix"
    44  )
    45  
    46  // DescriptionUndefined indicates the description is not defined
    47  const DescriptionUndefined = "description not defined"
    48  
    49  // GetCapabilitiesFromCluster will get capability from K8s cluster
    50  func GetCapabilitiesFromCluster(ctx context.Context, namespace string, c common.Args, selector labels.Selector) ([]types.Capability, error) {
    51  	caps, erl, err := GetComponentsFromCluster(ctx, namespace, c, selector)
    52  	for _, er := range erl {
    53  		klog.Infof("get component capability %v", er)
    54  	}
    55  	if err != nil {
    56  		return nil, err
    57  	}
    58  
    59  	traits, erl, err := GetTraitsFromCluster(ctx, namespace, c, selector)
    60  	if err != nil {
    61  		return nil, err
    62  	}
    63  	for _, er := range erl {
    64  		klog.Infof("get trait capability %v", er)
    65  	}
    66  	caps = append(caps, traits...)
    67  
    68  	plcs, erl, err := GetPolicies(ctx, namespace, c)
    69  	if err != nil {
    70  		return nil, err
    71  	}
    72  	for _, er := range erl {
    73  		klog.Infof("get policy capability %v", er)
    74  	}
    75  	caps = append(caps, plcs...)
    76  
    77  	wfs, erl, err := GetWorkflowSteps(ctx, namespace, c)
    78  	if err != nil {
    79  		return nil, err
    80  	}
    81  	for _, er := range erl {
    82  		klog.Infof("get workflow step %v", er)
    83  	}
    84  	caps = append(caps, wfs...)
    85  
    86  	return caps, nil
    87  }
    88  
    89  // GetNamespacedCapabilitiesFromCluster will get capability from K8s cluster in the specified namespace and default namespace
    90  // If the definition could be found from `namespace`, try to find in namespace `types.DefaultKubeVelaNS`
    91  func GetNamespacedCapabilitiesFromCluster(ctx context.Context, namespace string, c common.Args, selector labels.Selector) ([]types.Capability, error) {
    92  	var capabilities []types.Capability
    93  
    94  	if workloads, _, err := GetComponentsFromClusterWithValidateOption(ctx, namespace, c, selector, false); err == nil {
    95  		capabilities = append(capabilities, workloads...)
    96  	}
    97  
    98  	if traits, _, err := GetTraitsFromClusterWithValidateOption(ctx, namespace, c, selector, false); err == nil {
    99  		capabilities = append(capabilities, traits...)
   100  	}
   101  
   102  	if workflowSteps, _, err := GetWorkflowSteps(ctx, namespace, c); err == nil {
   103  		capabilities = append(capabilities, workflowSteps...)
   104  	}
   105  
   106  	if policies, _, err := GetPolicies(ctx, namespace, c); err == nil {
   107  		capabilities = append(capabilities, policies...)
   108  	}
   109  
   110  	if namespace != types.DefaultKubeVelaNS {
   111  		// get components from default namespace
   112  		if workloads, _, err := GetComponentsFromClusterWithValidateOption(ctx, types.DefaultKubeVelaNS, c, selector, false); err == nil {
   113  			capabilities = append(capabilities, workloads...)
   114  		}
   115  
   116  		// get traits from default namespace
   117  		if traits, _, err := GetTraitsFromClusterWithValidateOption(ctx, types.DefaultKubeVelaNS, c, selector, false); err == nil {
   118  			capabilities = append(capabilities, traits...)
   119  		}
   120  
   121  		if workflowSteps, _, err := GetWorkflowSteps(ctx, types.DefaultKubeVelaNS, c); err == nil {
   122  			capabilities = append(capabilities, workflowSteps...)
   123  		}
   124  
   125  		if policies, _, err := GetPolicies(ctx, types.DefaultKubeVelaNS, c); err == nil {
   126  			capabilities = append(capabilities, policies...)
   127  		}
   128  	}
   129  
   130  	if len(capabilities) > 0 {
   131  		return capabilities, nil
   132  	}
   133  	return nil, fmt.Errorf("could not find any components, traits or workflowSteps from namespace %s and %s", namespace, types.DefaultKubeVelaNS)
   134  }
   135  
   136  // GetComponentsFromCluster will get capability from K8s cluster
   137  func GetComponentsFromCluster(ctx context.Context, namespace string, c common.Args, selector labels.Selector) ([]types.Capability, []error, error) {
   138  	return GetComponentsFromClusterWithValidateOption(ctx, namespace, c, selector, true)
   139  }
   140  
   141  // GetComponentsFromClusterWithValidateOption will get capability from K8s cluster with an option whether to valid Components
   142  func GetComponentsFromClusterWithValidateOption(ctx context.Context, namespace string, c common.Args, selector labels.Selector, validateFlag bool) ([]types.Capability, []error, error) {
   143  	newClient, err := c.GetClient()
   144  	if err != nil {
   145  		return nil, nil, err
   146  	}
   147  
   148  	var templates []types.Capability
   149  	var componentsDefs v1beta1.ComponentDefinitionList
   150  	err = newClient.List(ctx, &componentsDefs, &client.ListOptions{Namespace: namespace, LabelSelector: selector})
   151  	if err != nil {
   152  		return nil, nil, fmt.Errorf("list ComponentDefinition err: %w", err)
   153  	}
   154  
   155  	var templateErrors []error
   156  	for _, cd := range componentsDefs.Items {
   157  		defRef := commontypes.DefinitionReference{
   158  			Name: cd.Spec.Workload.Type,
   159  		}
   160  		if cd.Spec.Workload.Type != types.AutoDetectWorkloadDefinition {
   161  			defRef, err = util.ConvertWorkloadGVK2Definition(newClient.RESTMapper(), cd.Spec.Workload.Definition)
   162  			if err != nil {
   163  				return nil, nil, err
   164  			}
   165  		}
   166  
   167  		tmp, err := GetCapabilityByComponentDefinitionObject(cd, defRef.Name)
   168  		if err != nil {
   169  			templateErrors = append(templateErrors, err)
   170  			continue
   171  		}
   172  		if validateFlag && defRef.Name != types.AutoDetectWorkloadDefinition {
   173  			if err = validateCapabilities(newClient.RESTMapper(), cd.Name, defRef); err != nil {
   174  				return nil, nil, err
   175  			}
   176  		}
   177  		templates = append(templates, *tmp)
   178  	}
   179  	return templates, templateErrors, nil
   180  }
   181  
   182  // GetTraitsFromCluster will get capability from K8s cluster
   183  func GetTraitsFromCluster(ctx context.Context, namespace string, c common.Args, selector labels.Selector) ([]types.Capability, []error, error) {
   184  	return GetTraitsFromClusterWithValidateOption(ctx, namespace, c, selector, true)
   185  }
   186  
   187  // GetTraitsFromClusterWithValidateOption will get capability from K8s cluster with an option whether to valid Traits
   188  func GetTraitsFromClusterWithValidateOption(ctx context.Context, namespace string, c common.Args, selector labels.Selector, validateFlag bool) ([]types.Capability, []error, error) {
   189  	newClient, err := c.GetClient()
   190  	if err != nil {
   191  		return nil, nil, err
   192  	}
   193  	var templates []types.Capability
   194  	var traitDefs v1beta1.TraitDefinitionList
   195  	err = newClient.List(ctx, &traitDefs, &client.ListOptions{Namespace: namespace, LabelSelector: selector})
   196  	if err != nil {
   197  		return nil, nil, fmt.Errorf("list TraitDefinition err: %w", err)
   198  	}
   199  
   200  	var templateErrors []error
   201  	for _, td := range traitDefs.Items {
   202  		var tmp *types.Capability
   203  		var err error
   204  		// FIXME: remove this temporary fix when https://github.com/cue-lang/cue/issues/2047 is fixed
   205  		if td.Name == "container-image" {
   206  			tmp = fix.CapContainerImage
   207  		} else {
   208  			tmp, err = GetCapabilityByTraitDefinitionObject(td)
   209  			if err != nil {
   210  				templateErrors = append(templateErrors, errors.Wrapf(err, "handle trait template `%s` failed", td.Name))
   211  				continue
   212  			}
   213  		}
   214  		tmp.Namespace = namespace
   215  		if validateFlag {
   216  			if err = validateCapabilities(newClient.RESTMapper(), td.Name, td.Spec.Reference); err != nil {
   217  				return nil, nil, err
   218  			}
   219  		}
   220  		templates = append(templates, *tmp)
   221  	}
   222  	return templates, templateErrors, nil
   223  }
   224  
   225  // GetWorkflowSteps will get WorkflowStepDefinition list
   226  func GetWorkflowSteps(ctx context.Context, namespace string, c common.Args) ([]types.Capability, []error, error) {
   227  	newClient, err := c.GetClient()
   228  	if err != nil {
   229  		return nil, nil, err
   230  	}
   231  
   232  	var templates []types.Capability
   233  	var workflowStepDefs v1beta1.WorkflowStepDefinitionList
   234  	err = newClient.List(ctx, &workflowStepDefs, &client.ListOptions{Namespace: namespace})
   235  	if err != nil {
   236  		return nil, nil, fmt.Errorf("list WorkflowStepDefinition err: %w", err)
   237  	}
   238  
   239  	config, err := c.GetConfig()
   240  	if err != nil {
   241  		return nil, nil, err
   242  	}
   243  	pd, err := packages.NewPackageDiscover(config)
   244  	if err != nil {
   245  		return nil, nil, err
   246  	}
   247  
   248  	var templateErrors []error
   249  	for _, def := range workflowStepDefs.Items {
   250  		tmp, err := GetCapabilityByWorkflowStepDefinitionObject(def, pd)
   251  		if err != nil {
   252  			templateErrors = append(templateErrors, errors.WithMessage(err, def.Name))
   253  			continue
   254  		}
   255  		templates = append(templates, *tmp)
   256  	}
   257  	return templates, templateErrors, nil
   258  }
   259  
   260  // GetPolicies will get Policy from K8s cluster
   261  func GetPolicies(ctx context.Context, namespace string, c common.Args) ([]types.Capability, []error, error) {
   262  	newClient, err := c.GetClient()
   263  	if err != nil {
   264  		return nil, nil, err
   265  	}
   266  
   267  	var templates []types.Capability
   268  	var defs v1beta1.PolicyDefinitionList
   269  	err = newClient.List(ctx, &defs, &client.ListOptions{Namespace: namespace})
   270  	if err != nil {
   271  		return nil, nil, fmt.Errorf("list PolicyDefinition err: %w", err)
   272  	}
   273  
   274  	var templateErrors []error
   275  	for _, def := range defs.Items {
   276  		tmp, err := GetCapabilityByPolicyDefinitionObject(def, nil)
   277  		if err != nil {
   278  			templateErrors = append(templateErrors, err)
   279  			continue
   280  		}
   281  		templates = append(templates, *tmp)
   282  	}
   283  	return templates, templateErrors, nil
   284  }
   285  
   286  // validateCapabilities validates whether GVK are successfully retrieved.
   287  func validateCapabilities(mapper meta.RESTMapper, definitionName string, reference commontypes.DefinitionReference) error {
   288  	_, err := util.GetGVKFromDefinition(mapper, reference)
   289  	if err != nil {
   290  		errMsg := err.Error()
   291  		var substr = "no matches for "
   292  		if strings.Contains(errMsg, substr) {
   293  			return fmt.Errorf("expected provider: %s", strings.Split(errMsg, substr)[1])
   294  		}
   295  		return fmt.Errorf("installing capability '%s'... %w", definitionName, err)
   296  	}
   297  	return nil
   298  }
   299  
   300  // HandleDefinition will handle definition to capability
   301  func HandleDefinition(name, crdName string, annotation, labels map[string]string, extension *runtime.RawExtension, tp types.CapType,
   302  	applyTo []string, schematic *commontypes.Schematic, pd *packages.PackageDiscover) (types.Capability, error) {
   303  	var tmp types.Capability
   304  	tmp, err := HandleTemplate(extension, schematic, name, pd)
   305  	if err != nil {
   306  		return types.Capability{}, err
   307  	}
   308  	tmp.Type = tp
   309  	if tp == types.TypeTrait {
   310  		tmp.AppliesTo = applyTo
   311  	}
   312  	tmp.CrdName = crdName
   313  	tmp.Description = GetDescription(annotation)
   314  	tmp.Example = GetExample(annotation)
   315  	tmp.Labels = labels
   316  	return tmp, nil
   317  }
   318  
   319  // GetDescription get description from annotation
   320  func GetDescription(annotation map[string]string) string {
   321  	if annotation == nil {
   322  		return DescriptionUndefined
   323  	}
   324  	desc, ok := annotation[types.AnnoDefinitionDescription]
   325  	if !ok {
   326  		return DescriptionUndefined
   327  	}
   328  	desc = strings.ReplaceAll(desc, "\n", " ")
   329  	return desc
   330  }
   331  
   332  // GetExample get example markdown from annotation specified url
   333  func GetExample(annotation map[string]string) string {
   334  	if annotation == nil {
   335  		return ""
   336  	}
   337  	examplePath, ok := annotation[types.AnnoDefinitionExampleURL]
   338  	if !ok {
   339  		return ""
   340  	}
   341  	if !utils.IsValidURL(examplePath) {
   342  		return ""
   343  	}
   344  	data, err := common.HTTPGetWithOption(context.Background(), examplePath, nil)
   345  	if err != nil {
   346  		return ""
   347  	}
   348  	if strings.HasSuffix(examplePath, ".yaml") {
   349  		return fmt.Sprintf("```yaml\n%s\n```", string(data))
   350  	}
   351  	return string(data)
   352  }
   353  
   354  // HandleTemplate will handle definition template to capability
   355  func HandleTemplate(in *runtime.RawExtension, schematic *commontypes.Schematic, name string, pd *packages.PackageDiscover) (types.Capability, error) {
   356  	tmp, err := appfile.ConvertTemplateJSON2Object(name, in, schematic)
   357  	if err != nil {
   358  		return types.Capability{}, err
   359  	}
   360  	tmp.Name = name
   361  	// if spec.template is not empty it should has the highest priority
   362  	if schematic != nil {
   363  		if schematic.CUE != nil {
   364  			tmp.CueTemplate = schematic.CUE.Template
   365  			tmp.CueTemplateURI = ""
   366  		}
   367  		if schematic.Terraform != nil {
   368  			tmp.Category = types.TerraformCategory
   369  			tmp.TerraformConfiguration = schematic.Terraform.Configuration
   370  			tmp.ConfigurationType = schematic.Terraform.Type
   371  			tmp.Path = schematic.Terraform.Path
   372  			return tmp, nil
   373  		}
   374  	}
   375  	if tmp.CueTemplateURI != "" {
   376  		b, err := common.HTTPGetWithOption(context.Background(), tmp.CueTemplateURI, nil)
   377  		if err != nil {
   378  			return types.Capability{}, err
   379  		}
   380  		tmp.CueTemplate = string(b)
   381  	}
   382  	if tmp.CueTemplate == "" {
   383  		return types.Capability{}, errors.New("template not exist in definition")
   384  	}
   385  	tmp.Parameters, err = cue.GetParameters(tmp.CueTemplate, pd)
   386  	if err != nil && !errors.Is(err, cue.ErrParameterNotExist) {
   387  		return types.Capability{}, err
   388  	}
   389  	tmp.Category = types.CUECategory
   390  	return tmp, nil
   391  }
   392  
   393  // GetCapabilityByName gets capability by definition name
   394  func GetCapabilityByName(ctx context.Context, c common.Args, capabilityName string, ns string, pd *packages.PackageDiscover) (*types.Capability, error) {
   395  	var (
   396  		foundCapability bool
   397  		capability      *types.Capability
   398  		err             error
   399  	)
   400  
   401  	newClient, err := c.GetClient()
   402  	if err != nil {
   403  		return nil, err
   404  	}
   405  	var componentDef v1beta1.ComponentDefinition
   406  	err = newClient.Get(ctx, client.ObjectKey{Namespace: ns, Name: capabilityName}, &componentDef)
   407  	if err == nil {
   408  		foundCapability = true
   409  	} else if kerrors.IsNotFound(err) {
   410  		err = newClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: capabilityName}, &componentDef)
   411  		if err == nil {
   412  			foundCapability = true
   413  		}
   414  	}
   415  
   416  	if foundCapability {
   417  		var refName string
   418  
   419  		// if workload type of ComponentDefinition is unclear,
   420  		// set the DefinitionReference's Name to AutoDetectWorkloadDefinition
   421  		if componentDef.Spec.Workload.Type == types.AutoDetectWorkloadDefinition {
   422  			refName = types.AutoDetectWorkloadDefinition
   423  		} else {
   424  			ref, err := util.ConvertWorkloadGVK2Definition(newClient.RESTMapper(), componentDef.Spec.Workload.Definition)
   425  			if err != nil {
   426  				return nil, err
   427  			}
   428  			refName = ref.Name
   429  		}
   430  
   431  		capability, err = GetCapabilityByComponentDefinitionObject(componentDef, refName)
   432  		if err != nil {
   433  			return nil, err
   434  		}
   435  		return capability, nil
   436  	}
   437  
   438  	foundCapability = false
   439  	var traitDef v1beta1.TraitDefinition
   440  	err = newClient.Get(ctx, client.ObjectKey{Namespace: ns, Name: capabilityName}, &traitDef)
   441  	if err == nil {
   442  		foundCapability = true
   443  	} else if kerrors.IsNotFound(err) {
   444  		err = newClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: capabilityName}, &traitDef)
   445  		if err == nil {
   446  			foundCapability = true
   447  		}
   448  	}
   449  	if foundCapability {
   450  		capability, err = GetCapabilityByTraitDefinitionObject(traitDef)
   451  		if err != nil {
   452  			return nil, err
   453  		}
   454  		return capability, nil
   455  	}
   456  
   457  	var wfStepDef v1beta1.WorkflowStepDefinition
   458  	err = newClient.Get(ctx, client.ObjectKey{Namespace: ns, Name: capabilityName}, &wfStepDef)
   459  	if err == nil {
   460  		foundCapability = true
   461  	} else if kerrors.IsNotFound(err) {
   462  		err = newClient.Get(ctx, client.ObjectKey{Namespace: types.DefaultKubeVelaNS, Name: capabilityName}, &wfStepDef)
   463  		if err == nil {
   464  			foundCapability = true
   465  		}
   466  	}
   467  	if foundCapability {
   468  		capability, err = GetCapabilityByWorkflowStepDefinitionObject(wfStepDef, pd)
   469  		if err != nil {
   470  			return nil, err
   471  		}
   472  		return capability, nil
   473  	}
   474  
   475  	if ns == types.DefaultKubeVelaNS {
   476  		return nil, fmt.Errorf("could not find %s in namespace %s", capabilityName, ns)
   477  	}
   478  	return nil, fmt.Errorf("could not find %s in namespace %s, or %s", capabilityName, ns, types.DefaultKubeVelaNS)
   479  }
   480  
   481  // GetCapabilityFromDefinitionRevision gets capabilities from the underlying Definition in DefinitionRevisions
   482  func GetCapabilityFromDefinitionRevision(ctx context.Context, c common.Args, pd *packages.PackageDiscover, ns, defName string, r int64) (*types.Capability, error) {
   483  	k8sClient, err := c.GetClient()
   484  	if err != nil {
   485  		return nil, err
   486  	}
   487  
   488  	revs, err := definition.SearchDefinitionRevisions(ctx, k8sClient, ns, defName, "", r)
   489  	if err != nil {
   490  		return nil, err
   491  	}
   492  	// `ns` defaults to `default` in `vela show`, if user doesn't specify anything,
   493  	// which often is not the desired behavior.
   494  	// So we need to search again in the vela-system namespace, if no revisions found.
   495  	// This behavior is consistent with the code above in GetCapabilityByName(), which also does double-search.
   496  	if len(revs) == 0 && ns == "default" {
   497  		revs, err = definition.SearchDefinitionRevisions(ctx, k8sClient, types.DefaultKubeVelaNS, defName, "", r)
   498  		if err != nil {
   499  			return nil, err
   500  		}
   501  	}
   502  	if len(revs) == 0 {
   503  		return nil, fmt.Errorf("no %s with revision %d found in namespace %s or %s", defName, r, ns, types.DefaultKubeVelaNS)
   504  	}
   505  
   506  	rev := revs[0]
   507  
   508  	switch rev.Spec.DefinitionType {
   509  	case commontypes.ComponentType:
   510  		var refName string
   511  		componentDef := rev.Spec.ComponentDefinition
   512  		// if workload type of ComponentDefinition is unclear,
   513  		// set the DefinitionReference's Name to AutoDetectWorkloadDefinition
   514  		if componentDef.Spec.Workload.Type == types.AutoDetectWorkloadDefinition {
   515  			refName = types.AutoDetectWorkloadDefinition
   516  		} else {
   517  			ref, err := util.ConvertWorkloadGVK2Definition(k8sClient.RESTMapper(), componentDef.Spec.Workload.Definition)
   518  			if err != nil {
   519  				return nil, err
   520  			}
   521  			refName = ref.Name
   522  		}
   523  		return GetCapabilityByComponentDefinitionObject(componentDef, refName)
   524  	case commontypes.TraitType:
   525  		return GetCapabilityByTraitDefinitionObject(rev.Spec.TraitDefinition)
   526  	case commontypes.WorkflowStepType:
   527  		return GetCapabilityByWorkflowStepDefinitionObject(rev.Spec.WorkflowStepDefinition, pd)
   528  	default:
   529  		return nil, fmt.Errorf("unsupported type %s", rev.Spec.DefinitionType)
   530  	}
   531  }
   532  
   533  // GetCapabilityByComponentDefinitionObject gets capability by ComponentDefinition object
   534  func GetCapabilityByComponentDefinitionObject(componentDef v1beta1.ComponentDefinition, referenceName string) (*types.Capability, error) {
   535  	capability, err := HandleDefinition(componentDef.Name, referenceName, componentDef.Annotations, componentDef.Labels,
   536  		componentDef.Spec.Extension, types.TypeComponentDefinition, nil, componentDef.Spec.Schematic, nil)
   537  	if err != nil {
   538  		return nil, errors.Wrap(err, "failed to handle ComponentDefinition")
   539  	}
   540  	capability.Namespace = componentDef.Namespace
   541  	return &capability, nil
   542  }
   543  
   544  // GetCapabilityByTraitDefinitionObject gets capability by TraitDefinition object
   545  func GetCapabilityByTraitDefinitionObject(traitDef v1beta1.TraitDefinition) (*types.Capability, error) {
   546  	var (
   547  		capability types.Capability
   548  		err        error
   549  	)
   550  	capability, err = HandleDefinition(traitDef.Name, traitDef.Spec.Reference.Name, traitDef.Annotations, traitDef.Labels,
   551  		traitDef.Spec.Extension, types.TypeTrait, nil, traitDef.Spec.Schematic, nil)
   552  	if err != nil {
   553  		return nil, errors.Wrap(err, "failed to handle TraitDefinition")
   554  	}
   555  	capability.Namespace = traitDef.Namespace
   556  	return &capability, nil
   557  }
   558  
   559  // GetCapabilityByWorkflowStepDefinitionObject gets capability by WorkflowStepDefinition object
   560  func GetCapabilityByWorkflowStepDefinitionObject(wfStepDef v1beta1.WorkflowStepDefinition, pd *packages.PackageDiscover) (*types.Capability, error) {
   561  	capability, err := HandleDefinition(wfStepDef.Name, wfStepDef.Spec.Reference.Name, wfStepDef.Annotations, wfStepDef.Labels,
   562  		nil, types.TypeWorkflowStep, nil, wfStepDef.Spec.Schematic, pd)
   563  	if err != nil {
   564  		return nil, errors.Wrap(err, "failed to handle WorkflowStepDefinition")
   565  	}
   566  	capability.Namespace = wfStepDef.Namespace
   567  	return &capability, nil
   568  }
   569  
   570  // GetCapabilityByPolicyDefinitionObject gets capability by PolicyDefinition object
   571  func GetCapabilityByPolicyDefinitionObject(def v1beta1.PolicyDefinition, pd *packages.PackageDiscover) (*types.Capability, error) {
   572  	capability, err := HandleDefinition(def.Name, def.Spec.Reference.Name, def.Annotations, def.Labels,
   573  		nil, types.TypePolicy, nil, def.Spec.Schematic, pd)
   574  	if err != nil {
   575  		return nil, errors.Wrap(err, "failed to handle PolicyDefinition")
   576  	}
   577  	capability.Namespace = def.Namespace
   578  	return &capability, nil
   579  }