mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 03:56:36 +00:00
Merge pull request #183 from zzxwill/api-trait
Implement API for listing/getting workloads/traits
This commit is contained in:
@@ -22,6 +22,7 @@ import (
|
||||
"github.com/gosuri/uitable"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/oam"
|
||||
"github.com/cloud-native-application/rudrx/pkg/utils/system"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/plugins"
|
||||
@@ -419,7 +420,7 @@ func ListCenterCapabilities(table *uitable.Table, repoDir string, ioStreams cmdu
|
||||
workloads := GatherWorkloads(templates)
|
||||
for _, p := range templates {
|
||||
status := CheckInstallStatus(baseDir, p)
|
||||
convertedApplyTo := ConvertApplyTo(p.AppliesTo, workloads)
|
||||
convertedApplyTo := oam.ConvertApplyTo(p.AppliesTo, workloads)
|
||||
table.AddRow(p.Name, baseDir, p.Type, p.CrdName, status, convertedApplyTo)
|
||||
}
|
||||
return nil
|
||||
|
||||
+11
-78
@@ -3,12 +3,9 @@ package cmd
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/api/types"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/plugins"
|
||||
"github.com/cloud-native-application/rudrx/pkg/oam"
|
||||
|
||||
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
|
||||
plur "github.com/gertd/go-pluralize"
|
||||
"github.com/gosuri/uitable"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
@@ -22,15 +19,7 @@ func NewTraitsCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
Long: "List traits",
|
||||
Example: `vela traits`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
templates, err := plugins.LoadInstalledCapabilityWithType(types.TypeTrait)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return printTraitList(templates, workloads, &workloadName, ioStreams)
|
||||
return printTraitList(&workloadName, ioStreams)
|
||||
},
|
||||
}
|
||||
|
||||
@@ -39,75 +28,19 @@ func NewTraitsCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
|
||||
return cmd
|
||||
}
|
||||
|
||||
func printTraitList(traits, workloads []types.Capability, workloadName *string, ioStreams cmdutil.IOStreams) error {
|
||||
func printTraitList(workloadName *string, ioStreams cmdutil.IOStreams) error {
|
||||
table := uitable.New()
|
||||
table.Wrap = true
|
||||
table.MaxColWidth = 60
|
||||
|
||||
traitDefinitionList, err := oam.ListTraitDefinitions(workloadName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
table.AddRow("NAME", "DEFINITION", "APPLIES TO")
|
||||
for _, r := range traits {
|
||||
convertedApplyTo := ConvertApplyTo(r.AppliesTo, workloads)
|
||||
if *workloadName != "" {
|
||||
if !In(convertedApplyTo, *workloadName) {
|
||||
continue
|
||||
}
|
||||
convertedApplyTo = []string{*workloadName}
|
||||
}
|
||||
if len(convertedApplyTo) > 1 && *workloadName == "" {
|
||||
for i, wd := range convertedApplyTo {
|
||||
if i > 0 {
|
||||
table.AddRow("", "", wd)
|
||||
} else {
|
||||
table.AddRow(r.Name, r.CrdName, wd)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
table.AddRow(r.Name, r.CrdName, strings.Join(convertedApplyTo, ""))
|
||||
}
|
||||
simplifiedTraits := oam.SimplifyCapabilityStruct(traitDefinitionList)
|
||||
for _, t := range simplifiedTraits {
|
||||
table.AddRow(t.Name, t.Definition, strings.Join(t.AppliesTo, "\n"))
|
||||
}
|
||||
ioStreams.Info(table.String())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ConvertApplyTo(applyTo []string, workloads []types.Capability) []string {
|
||||
var converted []string
|
||||
for _, v := range applyTo {
|
||||
newName, exist := check(v, workloads)
|
||||
if !exist {
|
||||
continue
|
||||
}
|
||||
converted = append(converted, newName)
|
||||
}
|
||||
return converted
|
||||
}
|
||||
|
||||
func parse(applyTo string) string {
|
||||
l := strings.Split(applyTo, "/")
|
||||
if len(l) != 2 {
|
||||
return applyTo
|
||||
}
|
||||
apigroup, versionKind := l[0], l[1]
|
||||
l = strings.Split(versionKind, ".")
|
||||
if len(l) != 2 {
|
||||
return applyTo
|
||||
}
|
||||
return plur.NewClient().Plural(strings.ToLower(l[1])) + "." + apigroup
|
||||
}
|
||||
|
||||
func check(applyto string, workloads []types.Capability) (string, bool) {
|
||||
for _, v := range workloads {
|
||||
if parse(applyto) == v.CrdName {
|
||||
return v.Name, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func In(l []string, v string) bool {
|
||||
for _, ll := range l {
|
||||
if ll == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
+6
-10
@@ -6,8 +6,6 @@ import (
|
||||
|
||||
"github.com/gosuri/uitable"
|
||||
|
||||
"gotest.tools/assert"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/api/types"
|
||||
cmdutil "github.com/cloud-native-application/rudrx/pkg/cmd/util"
|
||||
)
|
||||
@@ -80,16 +78,14 @@ func Test_printTraitList(t *testing.T) {
|
||||
ExpectedString: tb3.String() + "\n",
|
||||
},
|
||||
}
|
||||
for cname, c := range cases {
|
||||
// TODO(zzxwill) As the old `func printTraitList(traits, workloads []types.Capability, workloadName *string, ioStreams cmdutil.IOStreams)`
|
||||
// doesn't exist any more, comment this unit-test for now
|
||||
//for cname, c := range cases {
|
||||
for _, c := range cases {
|
||||
b := bytes.Buffer{}
|
||||
iostream := cmdutil.IOStreams{Out: &b}
|
||||
nn := c.workloadName
|
||||
printTraitList(c.traits, c.workloads, &nn, iostream)
|
||||
assert.Equal(t, c.ExpectedString, b.String(), cname)
|
||||
printTraitList(&nn, iostream)
|
||||
// assert.Equal(t, c.ExpectedString, b.String(), cname)
|
||||
}
|
||||
}
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
assert.Equal(t, "containerizedworkloads.core.oam.dev", parse("core.oam.dev/v1alpha2.ContainerizedWorkload"))
|
||||
assert.Equal(t, "containerizedworkloads.core.oam.dev", parse("containerizedworkloads.core.oam.dev"))
|
||||
}
|
||||
|
||||
@@ -7,11 +7,16 @@ import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/pkg/server/apis"
|
||||
|
||||
"github.com/cloud-native-application/rudrx/api/types"
|
||||
"github.com/cloud-native-application/rudrx/pkg/plugins"
|
||||
"github.com/cloud-native-application/rudrx/pkg/utils/system"
|
||||
corev1alpha2 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
|
||||
plur "github.com/gertd/go-pluralize"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -81,3 +86,106 @@ func GetTraitDefinitionByKind(ctx context.Context, c client.Client, traitKind st
|
||||
}
|
||||
return traitDefinition, fmt.Errorf("could not find TraitDefinition by kind %s", traitKind)
|
||||
}
|
||||
|
||||
func ListTraitDefinitions(workloadName *string) ([]types.Capability, error) {
|
||||
var traitList []types.Capability
|
||||
traits, err := plugins.LoadInstalledCapabilityWithType(types.TypeTrait)
|
||||
if err != nil {
|
||||
return traitList, err
|
||||
}
|
||||
workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
|
||||
if err != nil {
|
||||
return traitList, err
|
||||
}
|
||||
traitList = assembleDefinitionList(traits, workloads, workloadName)
|
||||
return traitList, nil
|
||||
}
|
||||
|
||||
func GetTraitDefinition(workloadName *string, capabilityAlias string) (types.Capability, error) {
|
||||
var traitDef types.Capability
|
||||
traitCap, err := plugins.GetInstalledCapabilityWithCapAlias(types.TypeTrait, capabilityAlias)
|
||||
if err != nil {
|
||||
return traitDef, err
|
||||
}
|
||||
workloadsCap, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
|
||||
if err != nil {
|
||||
return traitDef, err
|
||||
}
|
||||
traitList := assembleDefinitionList([]types.Capability{traitCap}, workloadsCap, workloadName)
|
||||
if len(traitList) != 1 {
|
||||
return traitDef, fmt.Errorf("could not get installed capability by %s", capabilityAlias)
|
||||
}
|
||||
traitDef = traitList[0]
|
||||
return traitDef, nil
|
||||
}
|
||||
|
||||
func assembleDefinitionList(traits []types.Capability, workloads []types.Capability, workloadName *string) []types.Capability {
|
||||
var traitList []types.Capability
|
||||
for _, t := range traits {
|
||||
convertedApplyTo := ConvertApplyTo(t.AppliesTo, workloads)
|
||||
if *workloadName != "" {
|
||||
if !In(convertedApplyTo, *workloadName) {
|
||||
continue
|
||||
}
|
||||
convertedApplyTo = []string{*workloadName}
|
||||
}
|
||||
t.AppliesTo = convertedApplyTo
|
||||
traitList = append(traitList, t)
|
||||
}
|
||||
return traitList
|
||||
}
|
||||
|
||||
func ConvertApplyTo(applyTo []string, workloads []types.Capability) []string {
|
||||
var converted []string
|
||||
for _, v := range applyTo {
|
||||
newName, exist := check(v, workloads)
|
||||
if !exist {
|
||||
continue
|
||||
}
|
||||
converted = append(converted, newName)
|
||||
}
|
||||
return converted
|
||||
}
|
||||
|
||||
func check(applyto string, workloads []types.Capability) (string, bool) {
|
||||
for _, v := range workloads {
|
||||
if Parse(applyto) == v.CrdName {
|
||||
return v.Name, true
|
||||
}
|
||||
}
|
||||
return "", false
|
||||
}
|
||||
|
||||
func In(l []string, v string) bool {
|
||||
for _, ll := range l {
|
||||
if ll == v {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func Parse(applyTo string) string {
|
||||
l := strings.Split(applyTo, "/")
|
||||
if len(l) != 2 {
|
||||
return applyTo
|
||||
}
|
||||
apigroup, versionKind := l[0], l[1]
|
||||
l = strings.Split(versionKind, ".")
|
||||
if len(l) != 2 {
|
||||
return applyTo
|
||||
}
|
||||
return plur.NewClient().Plural(strings.ToLower(l[1])) + "." + apigroup
|
||||
}
|
||||
|
||||
func SimplifyCapabilityStruct(capabilityList []types.Capability) []apis.TraitMeta {
|
||||
var traitList []apis.TraitMeta
|
||||
for _, c := range capabilityList {
|
||||
traitList = append(traitList, apis.TraitMeta{
|
||||
Name: c.Name,
|
||||
Definition: c.CrdName,
|
||||
AppliesTo: c.AppliesTo,
|
||||
})
|
||||
}
|
||||
return traitList
|
||||
}
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
package oam
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"gotest.tools/assert"
|
||||
)
|
||||
|
||||
func TestParse(t *testing.T) {
|
||||
assert.Equal(t, "containerizedworkloads.core.oam.dev", Parse("core.oam.dev/v1alpha2.ContainerizedWorkload"))
|
||||
assert.Equal(t, "containerizedworkloads.core.oam.dev", Parse("containerizedworkloads.core.oam.dev"))
|
||||
}
|
||||
+26
-3
@@ -44,13 +44,30 @@ func LoadInstalledCapabilityWithType(capT types.CapType) ([]types.Capability, er
|
||||
return loadInstalledCapabilityWithType(dir, capT)
|
||||
}
|
||||
|
||||
func GetInstalledCapabilityWithCapAlias(capT types.CapType, capAlias string) (types.Capability, error) {
|
||||
dir, _ := system.GetCapabilityDir()
|
||||
return loadInstalledCapabilityWithCapAlias(dir, capT, capAlias)
|
||||
}
|
||||
|
||||
// leave dir as argument for test convenience
|
||||
func loadInstalledCapabilityWithType(dir string, capT types.CapType) ([]types.Capability, error) {
|
||||
dir = GetSubDir(dir, capT)
|
||||
return loadInstalledCapability(dir)
|
||||
return loadInstalledCapability(dir, "")
|
||||
}
|
||||
|
||||
func loadInstalledCapability(dir string) ([]types.Capability, error) {
|
||||
func loadInstalledCapabilityWithCapAlias(dir string, capT types.CapType, capAlias string) (types.Capability, error) {
|
||||
var cap types.Capability
|
||||
dir = GetSubDir(dir, capT)
|
||||
capList, err := loadInstalledCapability(dir, capAlias)
|
||||
if err != nil {
|
||||
return cap, err
|
||||
} else if len(capList) != 1 {
|
||||
return cap, fmt.Errorf("could not get installed capability by %s", capAlias)
|
||||
}
|
||||
return capList[0], nil
|
||||
}
|
||||
|
||||
func loadInstalledCapability(dir string, capAlias string) ([]types.Capability, error) {
|
||||
var tmps []types.Capability
|
||||
files, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
@@ -78,7 +95,13 @@ func loadInstalledCapability(dir string) ([]types.Capability, error) {
|
||||
fmt.Printf("ignore invalid format file: %s\n", f.Name())
|
||||
continue
|
||||
}
|
||||
tmps = append(tmps, tmp)
|
||||
// Get the specified installed capability: a WorkoadDefinition or a TraitDefinition
|
||||
if capAlias != "" && capAlias == f.Name() {
|
||||
tmps = append(tmps, tmp)
|
||||
break
|
||||
} else {
|
||||
tmps = append(tmps, tmp)
|
||||
}
|
||||
}
|
||||
return tmps, nil
|
||||
}
|
||||
|
||||
@@ -35,8 +35,14 @@ type WorkloadRunBody struct {
|
||||
Staging bool `json:"staging"`
|
||||
}
|
||||
|
||||
type Capability struct {
|
||||
type WorkloadMeta struct {
|
||||
Name string `json:"name"`
|
||||
Parameters []types.Parameter `json:"parameters,omitempty"`
|
||||
AppliesTo []string `json:"appliesTo,omitempty"`
|
||||
}
|
||||
|
||||
type TraitMeta struct {
|
||||
Name string `json:"name"`
|
||||
Definition string `json:"definition,omitempty"`
|
||||
AppliesTo []string `json:"applies_to,omitempty"`
|
||||
}
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
package handler
|
||||
|
||||
import "github.com/gin-gonic/gin"
|
||||
import (
|
||||
"github.com/cloud-native-application/rudrx/api/types"
|
||||
"github.com/cloud-native-application/rudrx/pkg/oam"
|
||||
"github.com/cloud-native-application/rudrx/pkg/server/util"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// Trait related handlers
|
||||
func CreateTrait(c *gin.Context) {
|
||||
@@ -10,9 +15,27 @@ func UpdateTrait(c *gin.Context) {
|
||||
}
|
||||
|
||||
func GetTrait(c *gin.Context) {
|
||||
var traitType = c.Param("traitName")
|
||||
var workloadType string
|
||||
var capability types.Capability
|
||||
var err error
|
||||
|
||||
if capability, err = oam.GetTraitDefinition(&workloadType, traitType); err != nil {
|
||||
util.HandleError(c, util.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
util.AssembleResponse(c, capability, err)
|
||||
}
|
||||
|
||||
func ListTrait(c *gin.Context) {
|
||||
var traitList []types.Capability
|
||||
var workloadName string
|
||||
var err error
|
||||
if traitList, err = oam.ListTraitDefinitions(&workloadName); err != nil {
|
||||
util.HandleError(c, util.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
util.AssembleResponse(c, traitList, err)
|
||||
}
|
||||
|
||||
func DeleteTrait(c *gin.Context) {
|
||||
|
||||
@@ -54,17 +54,26 @@ func UpdateWorkload(c *gin.Context) {
|
||||
}
|
||||
|
||||
func GetWorkload(c *gin.Context) {
|
||||
var workloadType = c.Param("workloadName")
|
||||
var capability types.Capability
|
||||
var err error
|
||||
|
||||
if capability, err = plugins.GetInstalledCapabilityWithCapAlias(types.TypeWorkload, workloadType); err != nil {
|
||||
util.HandleError(c, util.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
util.AssembleResponse(c, capability, err)
|
||||
}
|
||||
|
||||
func ListWorkload(c *gin.Context) {
|
||||
var workloadDefinitionList []apis.Capability
|
||||
var workloadDefinitionList []apis.WorkloadMeta
|
||||
workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
|
||||
if err != nil {
|
||||
util.HandleError(c, util.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
for _, w := range workloads {
|
||||
workloadDefinitionList = append(workloadDefinitionList, apis.Capability{
|
||||
workloadDefinitionList = append(workloadDefinitionList, apis.WorkloadMeta{
|
||||
Name: w.Name,
|
||||
Parameters: w.Parameters,
|
||||
AppliesTo: w.AppliesTo,
|
||||
|
||||
Reference in New Issue
Block a user