diff --git a/apis/types/args.go b/apis/types/args.go
index 67df32b17..f4b4c3f08 100644
--- a/apis/types/args.go
+++ b/apis/types/args.go
@@ -3,6 +3,7 @@ package types
import (
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest"
+ "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config"
)
@@ -10,6 +11,7 @@ import (
type Args struct {
Config *rest.Config
Schema *runtime.Scheme
+ Client client.Client
}
// SetConfig insert kubeconfig into Args
@@ -21,3 +23,21 @@ func (a *Args) SetConfig() error {
a.Config = restConf
return nil
}
+
+// GetClient get client if exist
+func (a *Args) GetClient() (client.Client, error) {
+ if a.Config == nil {
+ if err := a.SetConfig(); err != nil {
+ return nil, err
+ }
+ }
+ if a.Client != nil {
+ return a.Client, nil
+ }
+ newClient, err := client.New(a.Config, client.Options{Scheme: a.Schema})
+ if err != nil {
+ return nil, err
+ }
+ a.Client = newClient
+ return a.Client, nil
+}
diff --git a/apis/types/capability.go b/apis/types/capability.go
index e8a447eeb..48797059b 100644
--- a/apis/types/capability.go
+++ b/apis/types/capability.go
@@ -43,7 +43,6 @@ type Capability struct {
CueTemplate string `json:"template,omitempty"`
CueTemplateURI string `json:"templateURI,omitempty"`
Parameters []Parameter `json:"parameters,omitempty"`
- DefinitionPath string `json:"definition"`
CrdName string `json:"crdName,omitempty"`
Center string `json:"center,omitempty"`
Status string `json:"status,omitempty"`
@@ -52,6 +51,9 @@ type Capability struct {
// trait only
AppliesTo []string `json:"appliesTo,omitempty"`
+ // Namespace represents it's a system-level or user-level capability.
+ Namespace string `json:"namespace,omitempty"`
+
// Plugin Source
Source *Source `json:"source,omitempty"`
Install *Installation `json:"install,omitempty"`
diff --git a/e2e/commonContext.go b/e2e/commonContext.go
index a399ad18e..59c904b88 100644
--- a/e2e/commonContext.go
+++ b/e2e/commonContext.go
@@ -136,7 +136,7 @@ var (
ginkgo.It("should list all applications", func() {
output, err := Exec("vela ls")
gomega.Expect(err).NotTo(gomega.HaveOccurred())
- gomega.Expect(output).To(gomega.ContainSubstring("SERVICE"))
+ gomega.Expect(output).To(gomega.ContainSubstring("COMPONENT"))
gomega.Expect(output).To(gomega.ContainSubstring(applicationName))
gomega.Expect(output).To(gomega.ContainSubstring(workloadType))
if traitAlias != "" {
diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go
index 3deb37e91..72cb49be7 100644
--- a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go
+++ b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go
@@ -83,7 +83,6 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
appParser := appfile.NewApplicationParser(r.Client, r.dm)
ctx = oamutil.SetNamespaceInCtx(ctx, app.Namespace)
-
appfile, err := appParser.GenerateAppFile(ctx, app.Name, app)
if err != nil {
applog.Error(err, "[Handle Parse]")
diff --git a/pkg/cue/convert.go b/pkg/cue/convert.go
index 777e9cafc..cd199423e 100644
--- a/pkg/cue/convert.go
+++ b/pkg/cue/convert.go
@@ -3,8 +3,6 @@ package cue
import (
"errors"
"fmt"
- "io/ioutil"
- "path/filepath"
"strings"
"cuelang.org/go/cue"
@@ -16,13 +14,9 @@ import (
const specValue = "parameter"
// GetParameters get parameter from cue template
-func GetParameters(templatePath string) ([]types.Parameter, error) {
+func GetParameters(templateStr string) ([]types.Parameter, error) {
r := cue.Runtime{}
- b, err := ioutil.ReadFile(filepath.Clean(templatePath))
- if err != nil {
- return nil, err
- }
- template, err := r.Compile("", string(b)+BaseTemplate)
+ template, err := r.Compile("", templateStr+BaseTemplate)
if err != nil {
return nil, err
}
diff --git a/pkg/cue/convert_test.go b/pkg/cue/convert_test.go
index cfc20bb79..4e5ec0e6c 100644
--- a/pkg/cue/convert_test.go
+++ b/pkg/cue/convert_test.go
@@ -1,6 +1,7 @@
package cue
import (
+ "io/ioutil"
"testing"
"cuelang.org/go/cue"
@@ -10,7 +11,8 @@ import (
)
func TestGetParameter(t *testing.T) {
- params, err := GetParameters("testdata/workloads/metrics.cue")
+ data, _ := ioutil.ReadFile("testdata/workloads/metrics.cue")
+ params, err := GetParameters(string(data))
assert.NoError(t, err)
assert.Equal(t, params, []types.Parameter{
{Name: "format", Required: false, Default: "prometheus", Usage: "format of the metrics, " +
@@ -19,8 +21,8 @@ func TestGetParameter(t *testing.T) {
{Name: "port", Required: false, Default: int64(8080), Type: cue.IntKind},
{Name: "selector", Required: false, Usage: "the label selector for the pods, default is the workload labels", Type: cue.StructKind},
})
-
- params, err = GetParameters("testdata/workloads/deployment.cue")
+ data, _ = ioutil.ReadFile("testdata/workloads/deployment.cue")
+ params, err = GetParameters(string(data))
assert.NoError(t, err)
assert.Equal(t, []types.Parameter{
{Name: "name", Required: true, Default: "", Type: cue.StringKind},
@@ -31,7 +33,8 @@ func TestGetParameter(t *testing.T) {
{Name: "cpu", Short: "", Required: false, Usage: "", Default: "", Type: cue.StringKind}},
params)
- params, err = GetParameters("testdata/workloads/test-param.cue")
+ data, _ = ioutil.ReadFile("testdata/workloads/test-param.cue")
+ params, err = GetParameters(string(data))
assert.NoError(t, err)
assert.Equal(t, []types.Parameter{
{Name: "name", Required: true, Default: "", Type: cue.StringKind},
@@ -41,7 +44,8 @@ func TestGetParameter(t *testing.T) {
{Name: "enable", Default: false, Type: cue.BoolKind},
{Name: "fval", Default: 64.3, Type: cue.FloatKind},
{Name: "nval", Default: float64(0), Required: true, Type: cue.NumberKind}}, params)
- params, err = GetParameters("testdata/workloads/empty.cue")
+ data, _ = ioutil.ReadFile("testdata/workloads/empty.cue")
+ params, err = GetParameters(string(data))
assert.NoError(t, err)
var exp []types.Parameter
assert.Equal(t, exp, params)
diff --git a/pkg/utils/helm/helm.go b/pkg/utils/helm/helm.go
index c5f2b019a..e883522c9 100644
--- a/pkg/utils/helm/helm.go
+++ b/pkg/utils/helm/helm.go
@@ -7,8 +7,6 @@ import (
"os"
"strings"
- "github.com/oam-dev/kubevela/pkg/utils/common"
-
"github.com/pkg/errors"
"helm.sh/helm/v3/pkg/action"
"helm.sh/helm/v3/pkg/chart"
@@ -17,9 +15,9 @@ import (
"helm.sh/helm/v3/pkg/getter"
"helm.sh/helm/v3/pkg/release"
"helm.sh/helm/v3/pkg/repo"
- "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/types"
+ "github.com/oam-dev/kubevela/pkg/utils/common"
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
)
@@ -39,7 +37,7 @@ func Install(ioStreams cmdutil.IOStreams, repoName, repoURL, chartName, version,
if err != nil {
return err
}
- kubeClient, err := client.New(args.Config, client.Options{Scheme: args.Schema})
+ kubeClient, err := args.GetClient()
if err != nil {
return err
}
diff --git a/references/apiserver/api-server.go b/references/apiserver/api-server.go
index c6f10fa58..ae1bef1e1 100644
--- a/references/apiserver/api-server.go
+++ b/references/apiserver/api-server.go
@@ -18,11 +18,12 @@ type APIServer struct {
server *http.Server
KubeClient client.Client
dm discoverymapper.DiscoveryMapper
+ c types.Args
}
// New will create APIServer
func New(c types.Args, port, staticPath string) (*APIServer, error) {
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return nil, err
}
@@ -33,6 +34,7 @@ func New(c types.Args, port, staticPath string) (*APIServer, error) {
s := &APIServer{
KubeClient: newClient,
dm: dm,
+ c: c,
}
server := &http.Server{
Addr: port,
diff --git a/references/apiserver/appHandlers.go b/references/apiserver/appHandlers.go
index 466502465..5fd7da4c8 100644
--- a/references/apiserver/appHandlers.go
+++ b/references/apiserver/appHandlers.go
@@ -107,7 +107,7 @@ func (s *APIServer) CreateApplication(c *gin.Context) {
IO: ioStream,
Env: env,
}
- buildResult, data, err := o.ExportFromAppFile(&body, false)
+ buildResult, data, err := o.ExportFromAppFile(&body, env.Namespace, false, s.c)
if err != nil {
util.HandleError(c, util.StatusInternalServerError, err.Error())
return
diff --git a/references/apiserver/capabilityHandlers.go b/references/apiserver/capabilityHandlers.go
index 62b7a260e..036e8c0dd 100644
--- a/references/apiserver/capabilityHandlers.go
+++ b/references/apiserver/capabilityHandlers.go
@@ -63,7 +63,8 @@ func (s *APIServer) DeleteCapabilityCenter(c *gin.Context) {
// RemoveCapabilityFromCluster remove a specific capability from cluster
func (s *APIServer) RemoveCapabilityFromCluster(c *gin.Context) {
capabilityCenterName := c.Param("capabilityName")
- msg, err := common.RemoveCapabilityFromCluster(s.KubeClient, capabilityCenterName)
+ // TODO get namespace from env
+ msg, err := common.RemoveCapabilityFromCluster("default", s.c, s.KubeClient, capabilityCenterName)
if err != nil {
util.HandleError(c, util.StatusInternalServerError, err.Error())
return
@@ -74,7 +75,7 @@ func (s *APIServer) RemoveCapabilityFromCluster(c *gin.Context) {
// ListCapabilities lists capabilities of a capability center
func (s *APIServer) ListCapabilities(c *gin.Context) {
capabilityCenterName := c.Param("capabilityName")
- capabilityList, err := common.ListCapabilities(capabilityCenterName)
+ capabilityList, err := common.ListCapabilities("default", s.c, capabilityCenterName)
if err != nil {
util.HandleError(c, util.StatusInternalServerError, err.Error())
return
diff --git a/references/apiserver/traitHandler.go b/references/apiserver/traitHandler.go
index b52450276..3b6da13c1 100644
--- a/references/apiserver/traitHandler.go
+++ b/references/apiserver/traitHandler.go
@@ -1,22 +1,12 @@
package apiserver
import (
- "context"
- "os"
- "strconv"
-
"github.com/gin-gonic/gin"
- "github.com/spf13/pflag"
- ctrl "sigs.k8s.io/controller-runtime"
"github.com/oam-dev/kubevela/apis/types"
- env2 "github.com/oam-dev/kubevela/pkg/utils/env"
- util2 "github.com/oam-dev/kubevela/pkg/utils/util"
"github.com/oam-dev/kubevela/references/apiserver/apis"
"github.com/oam-dev/kubevela/references/apiserver/util"
- "github.com/oam-dev/kubevela/references/appfile/api"
"github.com/oam-dev/kubevela/references/common"
- "github.com/oam-dev/kubevela/references/plugins"
)
// AttachTrait attaches a trait to a component
@@ -30,13 +20,8 @@ func (s *APIServer) AttachTrait(c *gin.Context) {
util.HandleError(c, util.InvalidArgument, "the trait attach request body is invalid")
return
}
- ctrl.Log.Info("request parameters body:", "body", body)
- msg, err := s.DoAttachTrait(c, body)
- if err != nil {
- util.HandleError(c, util.StatusInternalServerError, err.Error())
- return
- }
- util.AssembleResponse(c, msg, nil)
+
+ util.AssembleResponse(c, "deprecated, please use appfile to update", nil)
}
// GetTrait gets a trait by name
@@ -46,7 +31,7 @@ func (s *APIServer) GetTrait(c *gin.Context) {
var capability types.Capability
var err error
- if capability, err = common.GetTraitDefinition(&workloadType, traitType); err != nil {
+ if capability, err = common.GetTraitDefinition("default", s.c, &workloadType, traitType); err != nil {
util.HandleError(c, util.StatusInternalServerError, err)
return
}
@@ -58,7 +43,7 @@ func (s *APIServer) ListTrait(c *gin.Context) {
var traitList []types.Capability
var workloadName string
var err error
- if traitList, err = common.ListTraitDefinitions(&workloadName); err != nil {
+ if traitList, err = common.ListTraitDefinitions("default", s.c, &workloadName); err != nil {
util.HandleError(c, util.StatusInternalServerError, err)
return
}
@@ -67,77 +52,5 @@ func (s *APIServer) ListTrait(c *gin.Context) {
// DetachTrait detaches a trait from a component
func (s *APIServer) DetachTrait(c *gin.Context) {
- envName := c.Param("envName")
- traitType := c.Param("traitName")
- componentName := c.Param("compName")
- applicationName := c.Param("appName")
-
- var staging = false
- var err error
- if stagingStr := c.Param("staging"); stagingStr != "" {
- if staging, err = strconv.ParseBool(stagingStr); err != nil {
- util.HandleError(c, util.StatusInternalServerError, err.Error())
- return
- }
- }
- msg, err := s.DoDetachTrait(c, envName, traitType, componentName, applicationName, staging)
- if err != nil {
- util.HandleError(c, util.StatusInternalServerError, err.Error())
- return
- }
- util.AssembleResponse(c, msg, nil)
-}
-
-// DoAttachTrait executes attaching trait operation
-func (s *APIServer) DoAttachTrait(c context.Context, body apis.TraitBody) (string, error) {
- // Prepare
- var appObj *api.Application
- fs := pflag.NewFlagSet("trait", pflag.ContinueOnError)
- for _, f := range body.Flags {
- fs.String(f.Name, f.Value, "")
- }
- var staging = false
- var err error
- if body.Staging != "" {
- staging, err = strconv.ParseBool(body.Staging)
- if err != nil {
- return "", err
- }
- }
- traitAlias := body.Name
- template, err := plugins.GetInstalledCapabilityWithCapName(types.TypeTrait, traitAlias)
- if err != nil {
- return "", err
- }
- // Run step
- env, err := env2.GetEnvByName(body.EnvName)
- if err != nil {
- return "", err
- }
-
- appObj, err = common.AddOrUpdateTrait(env, body.AppName, body.ComponentName, fs, template)
- if err != nil {
- return "", err
- }
- io := util2.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
- return common.TraitOperationRun(c, s.KubeClient, env, appObj, staging, io)
-}
-
-// DoDetachTrait executes detaching trait operation
-func (s *APIServer) DoDetachTrait(c context.Context, envName string, traitType string, componentName string, appName string, staging bool) (string, error) {
- var appObj *api.Application
- var err error
- if appName == "" {
- appName = componentName
- }
- if appObj, err = common.PrepareDetachTrait(envName, traitType, componentName, appName); err != nil {
- return "", err
- }
- // Run
- env, err := env2.GetEnvByName(envName)
- if err != nil {
- return "", err
- }
- io := util2.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
- return common.TraitOperationRun(c, s.KubeClient, env, appObj, staging, io)
+ util.AssembleResponse(c, "deprecated, please use appfile to update", nil)
}
diff --git a/references/apiserver/workloadHandler.go b/references/apiserver/workloadHandler.go
index 0b7ae8d14..b24e55ec7 100644
--- a/references/apiserver/workloadHandler.go
+++ b/references/apiserver/workloadHandler.go
@@ -29,7 +29,7 @@ func (s *APIServer) GetWorkload(c *gin.Context) {
// ListWorkload lists all workloads in the cluster
func (s *APIServer) ListWorkload(c *gin.Context) {
var workloadDefinitionList []apis.WorkloadMeta
- workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
+ workloads, err := plugins.LoadInstalledCapabilityWithType("default", s.c, types.TypeWorkload)
if err != nil {
util.HandleError(c, util.StatusInternalServerError, err)
return
diff --git a/references/appfile/addon.go b/references/appfile/addon.go
index bff636a31..bbb9900e5 100644
--- a/references/appfile/addon.go
+++ b/references/appfile/addon.go
@@ -19,6 +19,7 @@ import (
"github.com/oam-dev/kubevela/pkg/appfile"
"github.com/oam-dev/kubevela/pkg/controller/utils"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
+ util2 "github.com/oam-dev/kubevela/pkg/oam/util"
"github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/pkg/utils/util"
)
@@ -36,8 +37,9 @@ func ApplyTerraform(app *v1alpha2.Application, k8sClient client.Client, ioStream
var nativeVelaComponents []v1alpha2.ApplicationComponent
// parse template
appParser := appfile.NewApplicationParser(k8sClient, dm)
- // TODO(wangyike) this context only for compiling success, lately mabey surport setting sysNs and appNs in api-server or cli
- appFile, err := appParser.GenerateAppFile(context.TODO(), app.Name, app)
+
+ ctx := util2.SetNamespaceInCtx(context.Background(), namespace)
+ appFile, err := appParser.GenerateAppFile(ctx, app.Name, app)
if err != nil {
return nil, fmt.Errorf("failed to parse appfile: %w", err)
}
diff --git a/references/appfile/api/driver.go b/references/appfile/api/driver.go
index d2cf8c2e2..73059bdfe 100644
--- a/references/appfile/api/driver.go
+++ b/references/appfile/api/driver.go
@@ -2,14 +2,10 @@ package api
// Driver is mutli implement interface
type Driver interface {
- // List applications
- List(envName string) ([]*Application, error)
// Save application
Save(app *Application, envName string) error
// Delete application
Delete(envName, appName string) error
- // Get application
- Get(envName, appName string) (*Application, error)
// Name of storage driver
Name() string
}
diff --git a/references/appfile/app.go b/references/appfile/app.go
index 1077c82ed..32c9c0e7a 100644
--- a/references/appfile/app.go
+++ b/references/appfile/app.go
@@ -2,6 +2,7 @@ package appfile
import (
"context"
+ "encoding/json"
"errors"
"fmt"
"reflect"
@@ -16,8 +17,8 @@ import (
)
// NewEmptyApplication new empty application, only set tm
-func NewEmptyApplication() (*api.Application, error) {
- tm, err := template.Load()
+func NewEmptyApplication(namespace string, c types.Args) (*api.Application, error) {
+ tm, err := template.Load(namespace, c)
if err != nil {
return nil, err
}
@@ -52,19 +53,17 @@ func Validate(app *api.Application) error {
return nil
}
-// IsNotFound is application not found error
-func IsNotFound(appName string, err error) bool {
- return err != nil && err.Error() == fmt.Sprintf(`application "%s" not found`, appName)
-}
-
-// LoadApplication will load application with env and name from default vela home dir.
-func LoadApplication(envName, appName string) (*api.Application, error) {
- app, err := GetStorage().Get(envName, appName)
+// LoadApplication will load application from cluster.
+func LoadApplication(namespace, appName string, c types.Args) (*v1alpha2.Application, error) {
+ newClient, err := c.GetClient()
if err != nil {
return nil, err
}
- err = Validate(app)
- return app, err
+ app := &v1alpha2.Application{}
+ if err := newClient.Get(context.TODO(), client.ObjectKey{Namespace: namespace, Name: appName}, app); err != nil {
+ return nil, err
+ }
+ return app, nil
}
// Delete will delete an app along with it's appfile.
@@ -72,50 +71,16 @@ func Delete(envName, appName string) error {
return GetStorage().Delete(envName, appName)
}
-// List will list all apps
-func List(envName string) ([]*api.Application, error) {
- respApps, err := GetStorage().List(envName)
- if err != nil {
- return nil, err
- }
- var apps []*api.Application
- for _, resp := range respApps {
- app := NewApplication(resp.AppFile, resp.Tm)
- err := Validate(app)
- if err != nil {
- return nil, err
- }
- apps = append(apps, app)
- }
- return apps, nil
-}
-
-// MatchAppByComp will get application with componentName without AppName.
-func MatchAppByComp(envName, compName string) (*api.Application, error) {
- apps, err := List(envName)
- if err != nil {
- return nil, err
- }
- for _, subapp := range apps {
- for _, v := range GetComponents(subapp) {
- if v == compName {
- return subapp, nil
- }
- }
- }
- return nil, fmt.Errorf("no app found contains %s in env %s", compName, envName)
-}
-
// Save will save appfile into default dir.
func Save(app *api.Application, envName string) error {
return GetStorage().Save(app, envName)
}
// GetComponents will get oam components from Appfile.
-func GetComponents(app *api.Application) []string {
+func GetComponents(app *v1alpha2.Application) []string {
var components []string
- for name := range app.Services {
- components = append(components, name)
+ for _, cmp := range app.Spec.Components {
+ components = append(components, cmp.Name)
}
sort.Strings(components)
return components
@@ -130,6 +95,18 @@ func GetServiceConfig(app *api.Application, componentName string) (string, map[s
return svc.GetType(), svc.GetApplicationConfig()
}
+// GetApplicationSettings will get service type and it's configuration
+func GetApplicationSettings(app *v1alpha2.Application, componentName string) (string, map[string]interface{}) {
+ for _, comp := range app.Spec.Components {
+ if comp.Name == componentName {
+ data := map[string]interface{}{}
+ _ = json.Unmarshal(comp.Settings.Raw, &data)
+ return comp.WorkloadType, data
+ }
+ }
+ return "", make(map[string]interface{})
+}
+
// GetWorkload will get workload type and it's configuration
func GetWorkload(app *api.Application, componentName string) (string, map[string]interface{}) {
svcType, config := GetServiceConfig(app, componentName)
@@ -163,33 +140,11 @@ func GetTraits(app *api.Application, componentName string) (map[string]map[strin
return traitsData, nil
}
-// GetTraitsByType will get trait configuration with specified component and trait type, we assume one type of trait can only attach to a component once.
-func GetTraitsByType(app *api.Application, componentName, traitType string) (map[string]interface{}, error) {
- service, ok := app.Services[componentName]
- if !ok {
- return nil, fmt.Errorf("service name (%s) doesn't exist", componentName)
- }
- t, ok := service[traitType]
- if !ok {
- return make(map[string]interface{}), nil
- }
- return t.(map[string]interface{}), nil
-}
-
// GetAppConfig will get AppConfig from K8s cluster.
-func GetAppConfig(ctx context.Context, c client.Client, app *api.Application, env *types.EnvMeta) (*v1alpha2.ApplicationConfiguration, error) {
+func GetAppConfig(ctx context.Context, c client.Client, app *v1alpha2.Application, env *types.EnvMeta) (*v1alpha2.ApplicationConfiguration, error) {
appConfig := &v1alpha2.ApplicationConfiguration{}
if err := c.Get(ctx, client.ObjectKey{Namespace: env.Namespace, Name: app.Name}, appConfig); err != nil {
return nil, err
}
return appConfig, nil
}
-
-// GetApplication will get Application from K8s cluster.
-func GetApplication(ctx context.Context, c client.Client, app *api.Application, env *types.EnvMeta) (*v1alpha2.Application, error) {
- appl := &v1alpha2.Application{}
- if err := c.Get(ctx, client.ObjectKey{Namespace: env.Namespace, Name: app.Name}, appl); err != nil {
- return nil, err
- }
- return appl, nil
-}
diff --git a/references/appfile/app_test.go b/references/appfile/app_test.go
index 0f01f1090..85d5f1c88 100644
--- a/references/appfile/app_test.go
+++ b/references/appfile/app_test.go
@@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"testing"
- "time"
"github.com/ghodss/yaml"
"github.com/stretchr/testify/assert"
@@ -128,7 +127,6 @@ services:
continue
}
assert.Equal(t, c.ExpName, app.Name, caseName)
- assert.Equal(t, c.ExpComponents, GetComponents(app), caseName)
workloadType, workload := GetWorkload(app, c.WantWorkload)
assert.Equal(t, c.ExpWorkload, workload, caseName)
assert.Equal(t, c.ExpWorkloadType, workloadType, caseName)
@@ -137,18 +135,3 @@ services:
assert.Equal(t, c.ExpTraits, traits, caseName)
}
}
-
-func TestLoadNotExistsApplication(t *testing.T) {
- caseName := "load not exists application"
-
- now := time.Now().Unix()
- appName := fmt.Sprintf("test-app-%d", now)
-
- app, err := LoadApplication(types.DefaultEnvName, appName)
-
- assert.Nil(t, app, caseName)
- assert.Error(t, err, caseName)
-
- errString := fmt.Sprintf(`application "%s" not found`, appName)
- assert.EqualError(t, err, errString, caseName)
-}
diff --git a/references/appfile/driver/local.go b/references/appfile/driver/local.go
index 276330c1d..33772d843 100644
--- a/references/appfile/driver/local.go
+++ b/references/appfile/driver/local.go
@@ -5,7 +5,6 @@ import (
"io/ioutil"
"os"
"path/filepath"
- "strings"
"time"
"github.com/ghodss/yaml"
@@ -13,7 +12,6 @@ import (
"github.com/oam-dev/kubevela/pkg/utils/env"
"github.com/oam-dev/kubevela/pkg/utils/system"
"github.com/oam-dev/kubevela/references/appfile/api"
- "github.com/oam-dev/kubevela/references/appfile/template"
)
// LocalDriverName is local storage driver name
@@ -34,33 +32,6 @@ func (l *Local) Name() string {
return LocalDriverName
}
-// List applications from local storage
-func (l *Local) List(envName string) ([]*api.Application, error) {
- appDir, err := getApplicationDir(envName)
- if err != nil {
- return nil, err
- }
- files, err := ioutil.ReadDir(appDir)
- if err != nil {
- return nil, fmt.Errorf("list apps from %s err %w", appDir, err)
- }
- var apps []*api.Application
- for _, f := range files {
- if f.IsDir() {
- continue
- }
- if !strings.HasSuffix(f.Name(), ".yaml") {
- continue
- }
- app, err := loadFromFile(filepath.Join(appDir, f.Name()))
- if err != nil {
- return nil, fmt.Errorf("load application err %w", err)
- }
- apps = append(apps, app)
- }
- return apps, nil
-}
-
// Save application from local storage
func (l *Local) Save(app *api.Application, envName string) error {
appDir, err := getApplicationDir(envName)
@@ -88,24 +59,6 @@ func (l *Local) Delete(envName, appName string) error {
return os.Remove(filepath.Join(appDir, appName+".yaml"))
}
-// Get application from local storage
-func (l *Local) Get(envName, appName string) (*api.Application, error) {
- appDir, err := getApplicationDir(envName)
- if err != nil {
- return nil, err
- }
- app, err := loadFromFile(filepath.Join(appDir, appName+".yaml"))
-
- if err != nil {
- if os.IsNotExist(err) {
- return nil, fmt.Errorf(`application "%s" not found`, appName)
- }
- return nil, err
- }
-
- return app, nil
-}
-
func getApplicationDir(envName string) (string, error) {
appDir := filepath.Join(env.GetEnvDirByName(envName), "applications")
_, err := system.CreateIfNotExist(appDir)
@@ -114,22 +67,3 @@ func getApplicationDir(envName string) (string, error) {
}
return appDir, err
}
-
-// LoadFromFile will load application from file
-func loadFromFile(fileName string) (*api.Application, error) {
- tm, err := template.Load()
- if err != nil {
- return nil, err
- }
- _, err = os.Stat(fileName)
- if err != nil {
- return nil, err
- }
-
- f, err := api.LoadFromFile(fileName)
- if err != nil {
- return nil, err
- }
- app := &api.Application{AppFile: f, Tm: tm}
- return app, nil
-}
diff --git a/references/appfile/driver/local_test.go b/references/appfile/driver/local_test.go
index 04eca1583..b10806f99 100644
--- a/references/appfile/driver/local_test.go
+++ b/references/appfile/driver/local_test.go
@@ -10,18 +10,15 @@ import (
"github.com/ghodss/yaml"
"github.com/oam-dev/kubevela/references/appfile/api"
- "github.com/oam-dev/kubevela/references/appfile/template"
)
var dir string
-var tm template.Manager
var afile *api.AppFile
var appName = "testsvc"
var envName = "default"
func init() {
dir, _ = getApplicationDir(envName)
- tm, _ = template.Load()
afile = api.NewAppFile()
afile.Name = appName
svcs := make(map[string]api.Service)
@@ -37,34 +34,6 @@ func init() {
_ = ioutil.WriteFile(filepath.Join(dir, appName+".yaml"), out, 0644)
}
-func TestLocal_Get(t *testing.T) {
- type args struct {
- envName string
- appName string
- }
- tests := []struct {
- name string
- args args
- want *api.Application
- wantErr bool
- }{
- {"TestLocal_Get1", args{envName: envName, appName: appName}, &api.Application{AppFile: afile, Tm: tm}, false},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- l := &Local{}
- got, err := l.Get(tt.args.envName, tt.args.appName)
- if (err != nil) != tt.wantErr {
- t.Errorf("Get() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if !reflect.DeepEqual(got, tt.want) {
- t.Errorf("Get() got = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
func TestLocal_Delete(t *testing.T) {
type args struct {
envName string
@@ -110,35 +79,6 @@ func TestLocal_Save(t *testing.T) {
}
}
-func TestLocal_List(t *testing.T) {
- type args struct {
- envName string
- }
- want := make([]*api.Application, 0)
- want = append(want, &api.Application{AppFile: afile, Tm: tm})
- tests := []struct {
- name string
- args args
- want []*api.Application
- wantErr bool
- }{
- {"TestLocal_List1", args{envName}, want, false},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- l := &Local{}
- got, err := l.List(tt.args.envName)
- if (err != nil) != tt.wantErr {
- t.Errorf("List() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if len(got) == 0 {
- t.Errorf("List() got = %v, want %v", got, tt.want)
- }
- })
- }
-}
-
func TestLocal_Name(t *testing.T) {
tests := []struct {
name string
@@ -197,29 +137,3 @@ func Test_getApplicationDir(t *testing.T) {
})
}
}
-
-func Test_loadFromFile(t *testing.T) {
- type args struct {
- fileName string
- }
- tests := []struct {
- name string
- args args
- want *api.Application
- wantErr bool
- }{
- {"testRespApp", args{fileName: filepath.Join(dir, appName+".yaml")}, &api.Application{AppFile: afile, Tm: tm}, false},
- }
- for _, tt := range tests {
- t.Run(tt.name, func(t *testing.T) {
- got, err := loadFromFile(tt.args.fileName)
- if (err != nil) != tt.wantErr {
- t.Errorf("loadFromFile() error = %v, wantErr %v", err, tt.wantErr)
- return
- }
- if got.Name != tt.want.Name {
- t.Errorf("loadFromFile() got = %v, want %v", got, tt.want)
- }
- })
- }
-}
diff --git a/references/appfile/modify.go b/references/appfile/modify.go
index eb5b39463..20d7b70a9 100644
--- a/references/appfile/modify.go
+++ b/references/appfile/modify.go
@@ -1,8 +1,13 @@
package appfile
import (
+ "encoding/json"
"errors"
+ "fmt"
+ "k8s.io/apimachinery/pkg/runtime"
+
+ "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/references/appfile/api"
)
@@ -25,30 +30,39 @@ func SetWorkload(app *api.Application, componentName, workloadType string, workl
}
// SetTrait will set user trait for Appfile
-func SetTrait(app *api.Application, componentName, traitType string, traitData map[string]interface{}) error {
+func SetTrait(app *v1alpha2.Application, componentName, traitType string, traitData map[string]interface{}) error {
if app == nil {
return errors.New("app is nil pointer")
}
if traitData == nil {
traitData = make(map[string]interface{})
}
-
- s, ok := app.Services[componentName]
- if !ok {
- s = api.Service{}
+ data, err := json.Marshal(traitData)
+ if err != nil {
+ return fmt.Errorf("fail to marshal trait data %w", err)
}
-
- t, ok := s[traitType]
- if !ok {
- t = make(map[string]interface{})
+ var foundComp bool
+ for idx, comp := range app.Spec.Components {
+ if comp.Name != componentName {
+ continue
+ }
+ foundComp = true
+ var added bool
+ for j, tr := range app.Spec.Components[idx].Traits {
+ if tr.Name != traitType {
+ continue
+ }
+ added = true
+ app.Spec.Components[idx].Traits[j].Properties.Raw = data
+ }
+ if !added {
+ app.Spec.Components[idx].Traits = append(app.Spec.Components[idx].Traits, v1alpha2.ApplicationTrait{Name: traitType, Properties: runtime.RawExtension{Raw: data}})
+ }
}
- tm := t.(map[string]interface{})
- for k, v := range traitData {
- tm[k] = v
+ if !foundComp {
+ return errors.New(componentName + " not found in app " + app.Name)
}
- s[traitType] = t
- app.Services[componentName] = s
- return Validate(app)
+ return nil
}
// RemoveTrait will remove a trait from Appfile
@@ -65,12 +79,18 @@ func RemoveTrait(app *api.Application, componentName, traitType string) error {
return nil
}
-// RemoveComponent will remove component from Appfile
-func RemoveComponent(app *api.Application, componentName string) error {
+// RemoveComponent will remove component from Application
+func RemoveComponent(app *v1alpha2.Application, componentName string) error {
if app == nil {
return errors.New("app is nil pointer")
}
-
- delete(app.Services, componentName)
+ var newComps []v1alpha2.ApplicationComponent
+ for _, comp := range app.Spec.Components {
+ if comp.Name == componentName {
+ continue
+ }
+ newComps = append(newComps, comp)
+ }
+ app.Spec.Components = newComps
return nil
}
diff --git a/references/appfile/storage.go b/references/appfile/storage.go
index d3a452097..4f86bc964 100644
--- a/references/appfile/storage.go
+++ b/references/appfile/storage.go
@@ -33,11 +33,6 @@ func GetStorage() *Storage {
return store
}
-// List applications storage common implement
-func (s *Storage) List(envName string) ([]*api.Application, error) {
- return s.Driver.List(envName)
-}
-
// Save application storage common implement
func (s *Storage) Save(app *api.Application, envName string) error {
return s.Driver.Save(app, envName)
@@ -47,8 +42,3 @@ func (s *Storage) Save(app *api.Application, envName string) error {
func (s *Storage) Delete(envName, appName string) error {
return s.Driver.Delete(envName, appName)
}
-
-// Get application storage common implement
-func (s *Storage) Get(envName, appName string) (*api.Application, error) {
- return s.Driver.Get(envName, appName)
-}
diff --git a/references/appfile/template/manager.go b/references/appfile/template/manager.go
index 22ff1104e..6ccd89d96 100644
--- a/references/appfile/template/manager.go
+++ b/references/appfile/template/manager.go
@@ -12,8 +12,8 @@ type Manager interface {
}
// Load will load all installed capabilities and create a manager
-func Load() (Manager, error) {
- caps, err := plugins.LoadAllInstalledCapability()
+func Load(namespace string, c types.Args) (Manager, error) {
+ caps, err := plugins.LoadAllInstalledCapability(namespace, c)
if err != nil {
return nil, err
}
diff --git a/references/cli/capability.go b/references/cli/capability.go
index 6ad08de1e..0535f1056 100644
--- a/references/cli/capability.go
+++ b/references/cli/capability.go
@@ -6,7 +6,6 @@ import (
"strings"
"github.com/spf13/cobra"
- "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
@@ -29,7 +28,7 @@ func CapabilityCommandGroup(c types.Args, ioStream cmdutil.IOStreams) *cobra.Com
}
cmd.AddCommand(
NewCenterCommand(ioStream),
- NewCapListCommand(ioStream),
+ NewCapListCommand(c, ioStream),
NewCapInstallCommand(c, ioStream),
NewCapUninstallCommand(c, ioStream),
)
@@ -94,7 +93,7 @@ func NewCapInstallCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Comm
if argsLength < 1 {
return errors.New("you must specify
/ for capability you want to install")
}
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return err
}
@@ -126,7 +125,7 @@ func NewCapUninstallCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Co
if len(args) < 1 {
return errors.New("you must specify for capability you want to uninstall")
}
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return err
}
@@ -138,7 +137,11 @@ func NewCapUninstallCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Co
}
name = l[1]
}
- return common.RemoveCapability(newClient, name, ioStreams)
+ env, err := GetEnv(cmd)
+ if err != nil {
+ return err
+ }
+ return common.RemoveCapability(env.Namespace, c, newClient, name, ioStreams)
},
}
cmd.PersistentFlags().StringP("token", "t", "", "Github Repo token")
@@ -168,7 +171,7 @@ func NewCapCenterSyncCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
}
// NewCapListCommand List capabilities from cap-center
-func NewCapListCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
+func NewCapListCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
cmd := &cobra.Command{
Use: "ls [cap-center]",
Short: "List capabilities from cap-center",
@@ -179,7 +182,11 @@ func NewCapListCommand(ioStreams cmdutil.IOStreams) *cobra.Command {
if len(args) > 0 {
repoName = args[0]
}
- capabilityList, err := common.ListCapabilities(repoName)
+ env, err := GetEnv(cmd)
+ if err != nil {
+ return err
+ }
+ capabilityList, err := common.ListCapabilities(env.Namespace, c, repoName)
if err != nil {
return err
}
diff --git a/references/cli/common.go b/references/cli/common.go
index 63245227b..c8b82d785 100644
--- a/references/cli/common.go
+++ b/references/cli/common.go
@@ -18,6 +18,7 @@ package cli
// constants used in `svc` command
const (
- App = "app"
- Service = "svc"
+ App = "app"
+ Service = "svc"
+ Namespace = "namespace"
)
diff --git a/references/cli/dashboard.go b/references/cli/dashboard.go
index 8206a2559..87845b35a 100644
--- a/references/cli/dashboard.go
+++ b/references/cli/dashboard.go
@@ -45,7 +45,7 @@ func NewDashboardCommand(c types.Args, ioStreams cmdutil.IOStreams, frontendSour
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return err
}
diff --git a/references/cli/delete.go b/references/cli/delete.go
index ad6a91430..096cd8789 100644
--- a/references/cli/delete.go
+++ b/references/cli/delete.go
@@ -5,7 +5,6 @@ import (
"github.com/spf13/cobra"
apierrors "k8s.io/apimachinery/pkg/api/errors"
- "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/types"
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
@@ -30,11 +29,13 @@ func NewDeleteCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command
cmd.SetOut(ioStreams.Out)
cmd.RunE = func(cmd *cobra.Command, args []string) error {
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return err
}
- o := &common.DeleteOptions{}
+ o := &common.DeleteOptions{
+ C: c,
+ }
o.Client = newClient
o.Env, err = GetEnv(cmd)
if err != nil {
diff --git a/references/cli/dryrun.go b/references/cli/dryrun.go
index 5f50d55a3..7c86eb4cf 100644
--- a/references/cli/dryrun.go
+++ b/references/cli/dryrun.go
@@ -8,7 +8,6 @@ import (
"github.com/pkg/errors"
"github.com/spf13/cobra"
- "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
corev1alpha2 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
@@ -37,7 +36,7 @@ func NewDryRunCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return err
}
@@ -54,7 +53,13 @@ func NewDryRunCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command
parser := appfile.NewApplicationParser(newClient, dm)
- ctx := oamutil.SetNamespaceInCtx(context.Background(), app.Namespace)
+ velaEnv, err := GetEnv(cmd)
+ if err != nil {
+ return err
+ }
+
+ ctx := oamutil.SetNamespaceInCtx(context.Background(), velaEnv.Namespace)
+
appFile, err := parser.GenerateAppFile(ctx, app.Name, app)
if err != nil {
return errors.WithMessage(err, "generate appFile")
diff --git a/references/cli/env.go b/references/cli/env.go
index 25f06cbdf..f11e2be65 100644
--- a/references/cli/env.go
+++ b/references/cli/env.go
@@ -64,15 +64,11 @@ func NewEnvInitCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return err
}
- if err := RefreshDefinitions(ctx, c, ioStreams, true, true); err != nil {
- return err
- }
-
return CreateOrUpdateEnv(ctx, newClient, &envArgs, args, ioStreams)
},
Annotations: map[string]string{
diff --git a/references/cli/exec.go b/references/cli/exec.go
index 83667eb65..72d14b9d2 100644
--- a/references/cli/exec.go
+++ b/references/cli/exec.go
@@ -14,12 +14,12 @@ import (
cmdexec "k8s.io/kubectl/pkg/cmd/exec"
k8scmdutil "k8s.io/kubectl/pkg/cmd/util"
+ "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/pkg/utils/util"
"github.com/oam-dev/kubevela/references/appfile"
- "github.com/oam-dev/kubevela/references/appfile/api"
)
const (
@@ -40,7 +40,7 @@ type VelaExecOptions struct {
context.Context
VelaC types.Args
Env *types.EnvMeta
- App *api.Application
+ App *v1alpha2.Application
f k8scmdutil.Factory
kcExecOptions *cmdexec.ExecOptions
@@ -122,7 +122,7 @@ func (o *VelaExecOptions) Init(ctx context.Context, c *cobra.Command, argsIn []s
return err
}
o.Env = env
- app, err := appfile.LoadApplication(env.Name, o.Args[0])
+ app, err := appfile.LoadApplication(env.Namespace, o.Args[0], o.VelaC)
if err != nil {
return err
}
@@ -167,8 +167,10 @@ func (o *VelaExecOptions) getComponentName() (string, error) {
svcName := o.ServiceName
if svcName != "" {
- if _, exist := o.App.Services[svcName]; exist {
- return svcName, nil
+ for _, cc := range o.App.Spec.Components {
+ if cc.Name == svcName {
+ return svcName, nil
+ }
}
o.Cmd.Printf("The service name '%s' is not valid\n", svcName)
}
diff --git a/references/cli/exec_test.go b/references/cli/exec_test.go
deleted file mode 100644
index 8999485f8..000000000
--- a/references/cli/exec_test.go
+++ /dev/null
@@ -1,101 +0,0 @@
-package cli
-
-import (
- "context"
- "fmt"
- "os"
- "testing"
-
- "github.com/oam-dev/kubevela/references/appfile/api"
-
- "github.com/spf13/cobra"
- "github.com/stretchr/testify/assert"
- corev1 "k8s.io/api/core/v1"
- v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- "k8s.io/cli-runtime/pkg/genericclioptions"
- "k8s.io/client-go/kubernetes/fake"
- "k8s.io/kubectl/pkg/cmd/exec"
- cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
- k8scmdutil "k8s.io/kubectl/pkg/cmd/util"
-
- "github.com/oam-dev/kubevela/apis/types"
- "github.com/oam-dev/kubevela/pkg/oam"
- cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
-)
-
-func TestExecCommand(t *testing.T) {
- tf := cmdtesting.NewTestFactory()
- defer tf.Cleanup()
- io := cmdutil.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
- fakeC := types.Args{
- Config: tf.ClientConfigVal,
- }
- cmd := NewExecCommand(fakeC, io)
- cmd.PersistentFlags().StringP("env", "e", "", "")
- o := &VelaExecOptions{
- kcExecOptions: &exec.ExecOptions{},
- f: tf,
- ClientSet: fake.NewSimpleClientset(&corev1.PodList{
- Items: []corev1.Pod{
- {
- ObjectMeta: v1.ObjectMeta{
- Name: "fakePod",
- Namespace: "default",
- Labels: map[string]string{
- oam.LabelAppName: "fakeApp",
- oam.LabelAppComponent: "fakeComp",
- }},
- },
- },
- }),
- }
- err := o.Init(context.Background(), cmd, []string{"fakeApp"})
- errString := fmt.Sprintf(`application "%s" not found`, "fakeApp")
- assert.EqualError(t, err, errString)
- fakeApp := &api.Application{
- AppFile: &api.AppFile{
- Name: "fakeApp",
- Services: map[string]api.Service{
- "fakeComp": map[string]interface{}{},
- },
- },
- }
- o.App = fakeApp
-
- cf := genericclioptions.NewConfigFlags(true)
- cf.Namespace = &o.Env.Namespace
- o.f = k8scmdutil.NewFactory(k8scmdutil.NewMatchVersionFlags(cf))
- err = o.Complete()
- assert.NoError(t, err)
-}
-
-func TestExecCommandPersistentPreRunE(t *testing.T) {
- io := cmdutil.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
- fakeC := types.Args{}
- cmd := NewExecCommand(fakeC, io)
- assert.Nil(t, cmd.PersistentPreRunE(new(cobra.Command), []string{}))
-}
-
-func TestGetComponent(t *testing.T) {
- o := &VelaExecOptions{
- App: &api.Application{
- AppFile: &api.AppFile{
- Name: "fakeApp",
- Services: map[string]api.Service{
- "fakeComp1": map[string]interface{}{},
- "fakeComp2": map[string]interface{}{},
- },
- },
- },
- }
-
- o.ServiceName = "fakeComp1"
- svcName, err := o.getComponentName()
- assert.NoError(t, err)
- assert.Equal(t, o.ServiceName, svcName)
-
- o.ServiceName = "fakeComp2"
- svcName, err = o.getComponentName()
- assert.NoError(t, err)
- assert.Equal(t, o.ServiceName, svcName)
-}
diff --git a/references/cli/export.go b/references/cli/export.go
index 3ba95ae3f..fd1303954 100644
--- a/references/cli/export.go
+++ b/references/cli/export.go
@@ -19,15 +19,19 @@ func NewExportCommand(c types.Args, ioStream cmdutil.IOStreams) *cobra.Command {
types.TagCommandType: types.TypeStart,
},
RunE: func(cmd *cobra.Command, args []string) error {
+ velaEnv, err := GetEnv(cmd)
+ if err != nil {
+ return err
+ }
o := &common.AppfileOptions{
IO: ioStream,
- Env: &types.EnvMeta{},
+ Env: velaEnv,
}
filePath, err := cmd.Flags().GetString(appFilePath)
if err != nil {
return err
}
- _, data, err := o.Export(filePath, true)
+ _, data, err := o.Export(filePath, velaEnv.Namespace, true, c)
if err != nil {
return err
}
diff --git a/references/cli/init.go b/references/cli/init.go
index 7f09577d8..53cbee65a 100644
--- a/references/cli/init.go
+++ b/references/cli/init.go
@@ -28,6 +28,7 @@ type appInitOptions struct {
client client.Client
cmdutil.IOStreams
Env *types.EnvMeta
+ c types.Args
app *api.Application
appName string
@@ -38,7 +39,7 @@ type appInitOptions struct {
// NewInitCommand creates `init` command
func NewInitCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
- o := &appInitOptions{IOStreams: ioStreams}
+ o := &appInitOptions{IOStreams: ioStreams, c: c}
cmd := &cobra.Command{
Use: "init",
DisableFlagsInUseLine: true,
@@ -49,7 +50,7 @@ func NewInitCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return err
}
@@ -69,9 +70,6 @@ func NewInitCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
if err = o.Workload(); err != nil {
return err
}
- if err = o.Traits(); err != nil {
- return err
- }
if err := appfile.Validate(o.app); err != nil {
return err
@@ -96,14 +94,14 @@ func NewInitCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
if err != nil {
return err
}
- deployStatus, err := printTrackingDeployStatus(ctx, o.client, o.IOStreams, o.workloadName, o.appName, o.Env)
+ deployStatus, err := printTrackingDeployStatus(c, o.IOStreams, o.appName, o.Env)
if err != nil {
return err
}
if deployStatus != compStatusDeployed {
return nil
}
- return printAppStatus(context.Background(), newClient, ioStreams, o.appName, o.Env, cmd)
+ return printAppStatus(context.Background(), newClient, ioStreams, o.appName, o.Env, cmd, c)
},
Annotations: map[string]string{
types.TagCommandType: types.TypeStart,
@@ -184,7 +182,7 @@ func formatAndGetUsage(p *types.Parameter) string {
// Workload asks user to choose workload type from installed workloads
func (o *appInitOptions) Workload() error {
- workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
+ workloads, err := plugins.LoadInstalledCapabilityWithType(o.Env.Namespace, o.c, types.TypeWorkload)
if err != nil {
return err
}
@@ -306,7 +304,7 @@ func (o *appInitOptions) Workload() error {
// other type not supported
}
}
- o.app, err = common.BaseComplete(o.Env.Name, o.workloadName, o.appName, fs, o.workloadType)
+ o.app, err = common.BaseComplete(o.Env, o.c, o.workloadName, o.appName, fs, o.workloadType)
return err
}
@@ -319,36 +317,3 @@ func GetCapabilityByName(name string, workloads []types.Capability) (types.Capab
}
return types.Capability{}, fmt.Errorf("%s not found", name)
}
-
-// Traits attaches specific trait to service
-func (o *appInitOptions) Traits() error {
- traits, err := plugins.LoadInstalledCapabilityWithType(types.TypeTrait)
- if err != nil {
- return err
- }
- switch o.workloadType {
- case "webservice":
- // TODO(wonderflow) this should get from workload definition to know which trait should be suggestions
- var suggestTraits = []string{}
- if o.Env.Domain != "" {
- suggestTraits = append(suggestTraits, "route")
- }
- for _, tr := range suggestTraits {
- trait, err := GetCapabilityByName(tr, traits)
- if err != nil {
- continue
- }
- tflags := pflag.NewFlagSet("trait", pflag.ContinueOnError)
- for _, pa := range trait.Parameters {
- types.SetFlagBy(tflags, pa)
- }
- // TODO(wonderflow): give a way to add parameter for trait
- o.app, err = common.AddOrUpdateTrait(o.Env, o.appName, o.workloadName, tflags, trait)
- if err != nil {
- return err
- }
- }
- default:
- }
- return nil
-}
diff --git a/references/cli/logs.go b/references/cli/logs.go
index 14a49b32d..5f8342ac9 100644
--- a/references/cli/logs.go
+++ b/references/cli/logs.go
@@ -15,11 +15,11 @@ import (
"k8s.io/apimachinery/pkg/labels"
"k8s.io/client-go/kubernetes"
+ "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/pkg/utils/util"
"github.com/oam-dev/kubevela/references/appfile"
- "github.com/oam-dev/kubevela/references/appfile/api"
)
// NewLogsCommand creates `logs` command to tail logs of application
@@ -45,7 +45,7 @@ func NewLogsCommand(c types.Args, ioStreams util.IOStreams) *cobra.Command {
if err != nil {
return err
}
- app, err := appfile.LoadApplication(env.Name, args[0])
+ app, err := appfile.LoadApplication(env.Namespace, args[0], c)
if err != nil {
return err
}
@@ -69,7 +69,7 @@ type Args struct {
Output string
Env *types.EnvMeta
C types.Args
- App *api.Application
+ App *v1alpha2.Application
}
// Run refer to the implementation at https://github.com/oam-dev/stern/blob/master/stern/main.go
diff --git a/references/cli/ls.go b/references/cli/ls.go
index f72d40e45..515f3d93b 100644
--- a/references/cli/ls.go
+++ b/references/cli/ls.go
@@ -5,14 +5,12 @@ import (
"strings"
"github.com/spf13/cobra"
+ apierrors "k8s.io/apimachinery/pkg/api/errors"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/types"
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
- "github.com/oam-dev/kubevela/references/apiserver/apis"
- "github.com/oam-dev/kubevela/references/appfile"
- "github.com/oam-dev/kubevela/references/common"
)
// NewListCommand creates `ls` command and its nested children command
@@ -22,8 +20,8 @@ func NewListCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
Use: "ls",
Aliases: []string{"list"},
DisableFlagsInUseLine: true,
- Short: "List services",
- Long: "List services of all applications",
+ Short: "List applications",
+ Long: "List all applications in cluster",
Example: `vela ls`,
PersistentPreRunE: func(cmd *cobra.Command, args []string) error {
return c.SetConfig()
@@ -33,98 +31,64 @@ func NewListCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
if err != nil {
return err
}
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return err
}
- appName, err := cmd.Flags().GetString(App)
+ namespace, err := cmd.Flags().GetString(Namespace)
if err != nil {
return err
}
- printComponentList(ctx, newClient, appName, env, ioStreams)
- return nil
+ if namespace == "" {
+ namespace = env.Namespace
+ }
+ return printApplicationList(ctx, newClient, namespace, ioStreams)
},
Annotations: map[string]string{
types.TagCommandType: types.TypeApp,
},
}
- cmd.PersistentFlags().StringP(App, "", "", "specify the name of application")
+ cmd.PersistentFlags().StringP(Namespace, "n", "", "specify the namespace the application want to list, default is the current env namespace")
return cmd
}
-func printComponentList(ctx context.Context, c client.Reader, appName string, env *types.EnvMeta,
- ioStreams cmdutil.IOStreams) {
- deployedComponentList, err := common.ListComponents(ctx, c, common.Option{
- AppName: appName,
- Namespace: env.Namespace,
- })
- if err != nil {
- ioStreams.Infof("listing services: %s\n", err)
- return
+func printApplicationList(ctx context.Context, c client.Reader, namespace string, ioStreams cmdutil.IOStreams) error {
+ table := newUITable()
+ table.AddRow("APP", "COMPONENT", "TYPE", "TRAITS", "PHASE", "HEALTHY", "STATUS", "CREATED-TIME")
+ applist := v1alpha2.ApplicationList{}
+ if err := c.List(ctx, &applist, client.InNamespace(namespace)); err != nil {
+ if apierrors.IsNotFound(err) {
+ ioStreams.Info(table.String())
+ return nil
+ }
+ return err
}
- fetcher := func(name string) (*v1alpha2.Application, error) {
- var app = new(v1alpha2.Application)
- err := c.Get(ctx, client.ObjectKey{Name: name, Namespace: env.Namespace}, app)
- return app, err
- }
- all := mergeStagingComponents(deployedComponentList, env, ioStreams, fetcher)
- table := newUITable()
- table.AddRow("SERVICE", "APP", "TYPE", "TRAITS", "STATUS", "CREATED-TIME")
- for _, a := range all {
- traitAlias := strings.Join(a.TraitNames, ",")
- table.AddRow(a.Name, a.App, a.WorkloadName, traitAlias, a.Status, a.CreatedTime)
+ for _, a := range applist.Items {
+ for idx, cmp := range a.Spec.Components {
+ var appName = a.Name
+ if idx > 0 {
+ appName = "├─"
+ if idx == len(a.Spec.Components)-1 {
+ appName = "└─"
+ }
+ }
+ var healthy, status string
+ if len(a.Status.Services) > idx {
+ if a.Status.Services[idx].Healthy {
+ healthy = "healthy"
+ } else {
+ healthy = "unhealthy"
+ }
+ status = a.Status.Services[idx].Message
+ }
+ var traits []string
+ for _, tr := range cmp.Traits {
+ traits = append(traits, tr.Name)
+ }
+ table.AddRow(appName, cmp.Name, cmp.WorkloadType, strings.Join(traits, ","), a.Status.Phase, healthy, status, a.CreationTimestamp)
+ }
}
ioStreams.Info(table.String())
-}
-
-func mergeStagingComponents(deployed []apis.ComponentMeta, env *types.EnvMeta, ioStreams cmdutil.IOStreams, fetcher func(name string) (*v1alpha2.Application, error)) []apis.ComponentMeta {
- localApps, err := appfile.List(env.Name)
- if err != nil {
- ioStreams.Error("list application err", err)
- return deployed
- }
- var all []apis.ComponentMeta
- for _, app := range localApps {
- appl, err := fetcher(app.Name)
- if err != nil {
- ioStreams.Errorf("fetch app %s err %v\n", app.Name, err)
- continue
- }
- for _, c := range appl.Spec.Components {
- traits := []string{}
- for _, t := range c.Traits {
- traits = append(traits, t.Name)
- }
- compMeta, exist := GetCompMeta(deployed, app.Name, c.Name)
- if !exist {
- all = append(all, apis.ComponentMeta{
- Name: c.Name,
- App: app.Name,
- WorkloadName: c.WorkloadType,
- TraitNames: traits,
- Status: types.StatusStaging,
- CreatedTime: app.CreateTime.String(),
- })
- continue
- }
- compMeta.TraitNames = traits
- compMeta.WorkloadName = c.WorkloadType
- if appl.Status.Phase != v1alpha2.ApplicationRunning {
- compMeta.Status = types.StatusStaging
- }
- all = append(all, compMeta)
- }
- }
- return all
-}
-
-// GetCompMeta gets meta of a component
-func GetCompMeta(deployed []apis.ComponentMeta, appName, compName string) (apis.ComponentMeta, bool) {
- for _, v := range deployed {
- if v.Name == compName && v.App == appName {
- return v, true
- }
- }
- return apis.ComponentMeta{}, false
+ return nil
}
diff --git a/references/cli/portforward.go b/references/cli/portforward.go
index 0846913b7..15f3f0726 100644
--- a/references/cli/portforward.go
+++ b/references/cli/portforward.go
@@ -28,7 +28,6 @@ import (
"github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/pkg/utils/util"
"github.com/oam-dev/kubevela/references/appfile"
- "github.com/oam-dev/kubevela/references/appfile/api"
)
// VelaPortForwardOptions for vela port-forward
@@ -40,7 +39,7 @@ type VelaPortForwardOptions struct {
context.Context
VelaC types.Args
Env *types.EnvMeta
- App *api.Application
+ App *v1alpha2.Application
f k8scmdutil.Factory
kcPortForwardOptions *cmdpf.PortForwardOptions
@@ -74,7 +73,7 @@ func NewPortForwardCommand(c types.Args, ioStreams util.IOStreams) *cobra.Comman
ioStreams.Error("Please specify application name.")
return nil
}
- newClient, err := client.New(o.VelaC.Config, client.Options{Scheme: o.VelaC.Schema})
+ newClient, err := o.VelaC.GetClient()
if err != nil {
return err
}
@@ -114,7 +113,7 @@ func (o *VelaPortForwardOptions) Init(ctx context.Context, cmd *cobra.Command, a
}
o.Env = env
- app, err := appfile.LoadApplication(env.Name, o.Args[0])
+ app, err := appfile.LoadApplication(env.Namespace, o.Args[0], o.VelaC)
if err != nil {
return err
}
@@ -191,7 +190,7 @@ func (o *VelaPortForwardOptions) Complete() error {
}
if len(o.Args) < 2 {
var found bool
- _, configs := appfile.GetServiceConfig(o.App, svcName)
+ _, configs := appfile.GetApplicationSettings(o.App, svcName)
for k, v := range configs {
if k == "port" {
var val string
diff --git a/references/cli/portforward_test.go b/references/cli/portforward_test.go
deleted file mode 100644
index ca7bdd831..000000000
--- a/references/cli/portforward_test.go
+++ /dev/null
@@ -1,62 +0,0 @@
-package cli
-
-import (
- "context"
- "fmt"
- "os"
- "testing"
-
- "github.com/spf13/cobra"
- "github.com/stretchr/testify/assert"
- corev1 "k8s.io/api/core/v1"
- v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
- k8sfake "k8s.io/client-go/kubernetes/fake"
- "k8s.io/kubectl/pkg/cmd/portforward"
- cmdtesting "k8s.io/kubectl/pkg/cmd/testing"
-
- "github.com/oam-dev/kubevela/apis/types"
- "github.com/oam-dev/kubevela/pkg/oam"
- cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
-)
-
-func TestPortForwardCommand(t *testing.T) {
- fakePod := corev1.Pod{
- ObjectMeta: v1.ObjectMeta{
- Name: "fakePod",
- Namespace: "default",
- ResourceVersion: "10",
- Labels: map[string]string{
- oam.LabelAppComponent: "fakeComp",
- }},
- }
- tf := cmdtesting.NewTestFactory()
- defer tf.Cleanup()
-
- io := cmdutil.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
- fakeC := types.Args{
- Config: tf.ClientConfigVal,
- }
- cmd := NewPortForwardCommand(fakeC, io)
- cmd.PersistentFlags().StringP("env", "e", "", "")
- fakeClientSet := k8sfake.NewSimpleClientset(&corev1.PodList{
- Items: []corev1.Pod{fakePod},
- })
-
- o := &VelaPortForwardOptions{
- ioStreams: io,
- kcPortForwardOptions: &portforward.PortForwardOptions{},
- f: tf,
- ClientSet: fakeClientSet,
- VelaC: fakeC,
- }
- err := o.Init(context.Background(), cmd, []string{"fakeApp", "8081:8080"})
- errString := fmt.Sprintf(`application "%s" not found`, "fakeApp")
- assert.EqualError(t, err, errString)
-}
-
-func TestNewPortForwardCommandPersistentPreRunE(t *testing.T) {
- io := cmdutil.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
- fakeC := types.Args{}
- cmd := NewPortForwardCommand(fakeC, io)
- assert.Nil(t, cmd.PersistentPreRunE(new(cobra.Command), []string{}))
-}
diff --git a/references/cli/refresh.go b/references/cli/refresh.go
deleted file mode 100644
index 2a2a78e45..000000000
--- a/references/cli/refresh.go
+++ /dev/null
@@ -1,285 +0,0 @@
-package cli
-
-import (
- "context"
- "encoding/json"
- "io/ioutil"
- "os"
- "path/filepath"
- "strconv"
- "time"
-
- "github.com/fatih/color"
- "github.com/gosuri/uitable"
- "github.com/mitchellh/hashstructure/v2"
-
- "github.com/oam-dev/kubevela/apis/types"
- "github.com/oam-dev/kubevela/pkg/utils/system"
- cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
- "github.com/oam-dev/kubevela/references/plugins"
-)
-
-type refreshStatus string
-
-const (
- added refreshStatus = "Added"
- updated refreshStatus = "Updated"
- unchanged refreshStatus = "Unchanged"
- deleted refreshStatus = "Deleted"
-)
-
-const (
- refreshInterval = 5 * time.Minute
-)
-
-// RefreshDefinitions will sync local capabilities with cluster installed ones
-func RefreshDefinitions(ctx context.Context, c types.Args, ioStreams cmdutil.IOStreams, silentOutput, enforceRefresh bool) error {
- dir, _ := system.GetCapabilityDir()
- oldCaps, err := plugins.LoadAllInstalledCapability()
- if err != nil {
- return err
- }
- useCached, err := useCacheInsteadRefresh(dir, refreshInterval)
- if err != nil {
- return err
- }
- if !enforceRefresh && useCached {
- // use local capabilities instead of fetching from cluster
- printRefreshReport(nil, oldCaps, ioStreams, silentOutput, true)
- return nil
- }
-
- syncedTemplates, warnings, err := plugins.SyncDefinitionsToLocal(ctx, c, dir)
- if err != nil {
- return err
- }
- for _, w := range warnings {
- ioStreams.Infof(w)
- }
- plugins.RemoveLegacyTemps(syncedTemplates, dir)
- printRefreshReport(syncedTemplates, oldCaps, ioStreams, silentOutput, false)
- return nil
-}
-
-// silent indicates whether output existing caps if no change occurs. If false, output all existing caps.
-func printRefreshReport(newCaps, oldCaps []types.Capability, io cmdutil.IOStreams, silent, useCached bool) {
- var report map[refreshStatus][]types.Capability
- if useCached {
- report = map[refreshStatus][]types.Capability{
- added: make([]types.Capability, 0),
- updated: make([]types.Capability, 0),
- unchanged: oldCaps,
- deleted: make([]types.Capability, 0),
- }
- } else {
- report = refreshResultReport(newCaps, oldCaps)
- }
- table := newUITable()
- table.MaxColWidth = 80
- table.AddRow("TYPE", "CATEGORY", "DESCRIPTION")
-
- if len(report[added]) == 0 && len(report[updated]) == 0 && len(report[deleted]) == 0 {
- // no change occurs, just show all existing caps
- // always show workload at first
- for _, cap := range report[unchanged] {
- if cap.Type == types.TypeWorkload {
- table.AddRow(cap.Name, cap.Type, cap.Description)
- }
- }
- for _, cap := range report[unchanged] {
- if cap.Type == types.TypeTrait {
- table.AddRow(cap.Name, cap.Type, cap.Description)
- }
- }
- if !silent {
- io.Infof("Automatically discover capabilities successfully %s(no changes)\n\n", emojiSucceed)
- io.Info(table.String())
- }
- return
- }
-
- io.Infof("Automatically discover capabilities successfully %sAdd(%s) Update(%s) Delete(%s)\n\n",
- emojiSucceed,
- green.Sprint(len(report[added])),
- yellow.Sprint(len(report[updated])),
- red.Sprint(len(report[deleted])))
- // show added/updated/deleted cpas
- addStsRow(added, report, table)
- addStsRow(updated, report, table)
- addStsRow(deleted, report, table)
- io.Info(table.String())
- io.Info()
-}
-
-func addStsRow(sts refreshStatus, report map[refreshStatus][]types.Capability, t *uitable.Table) {
- caps := report[sts]
- if len(caps) == 0 {
- return
- }
- var stsIcon string
- var stsColor *color.Color
- switch sts {
- case added:
- stsIcon = "+"
- stsColor = green
- case updated:
- stsIcon = "*"
- stsColor = yellow
- case deleted:
- stsIcon = "-"
- stsColor = red
- case unchanged:
- // normal color display
- }
- for _, cap := range caps {
- t.AddRow(
- // color.New(color.Bold).Sprint(stsColor.Sprint(stsIcon)),
- stsColor.Sprintf("%s%s", stsIcon, cap.Name),
- stsColor.Sprint(cap.Type),
- stsColor.Sprint(cap.Description))
- }
-}
-
-func refreshResultReport(newCaps, oldCaps []types.Capability) map[refreshStatus][]types.Capability {
- dir, _ := system.GetCapabilityDir()
- cachedHash := readCapDefHashFromLocal(dir)
- newHash := map[string]string{}
- for _, newCap := range newCaps {
- h, err := hashstructure.Hash(newCap, hashstructure.FormatV2, nil)
- if err != nil {
- continue
- }
- newHash[newCap.Name] = strconv.FormatUint(h, 10)
- }
-
- report := map[refreshStatus][]types.Capability{
- added: make([]types.Capability, 0),
- updated: make([]types.Capability, 0),
- unchanged: make([]types.Capability, 0),
- deleted: make([]types.Capability, 0),
- }
- for _, newCap := range newCaps {
- found := false
- for _, oldCap := range oldCaps {
- if newCap.Name == oldCap.Name {
- found = true
- break
- }
- }
- if !found {
- report[added] = append(report[added], newCap)
- }
- }
- for _, oldCap := range oldCaps {
- found := false
- for _, newCap := range newCaps {
- if oldCap.Name == newCap.Name {
- found = true
- // use cached hash to determine whether the cap is changed
- if h, ok := cachedHash[newCap.Name]; ok {
- if h == newHash[newCap.Name] {
- report[unchanged] = append(report[unchanged], newCap)
- } else {
- report[updated] = append(report[updated], newCap)
- }
- break
- }
- // in case of missing cache, use Equal func to compare
- if types.EqualCapability(oldCap, newCap) {
- report[unchanged] = append(report[unchanged], newCap)
- } else {
- report[updated] = append(report[updated], newCap)
- }
- break
- }
- }
- if !found {
- report[deleted] = append(report[deleted], oldCap)
- }
- }
- _ = writeCapDefHashIntoLocal(dir, newHash)
- return report
-}
-
-// useCacheInsteadRefresh checks whether use cached capabilities instead of refresh from cluster
-// a timestamp records the time when refresh from cluster last time
-// if duration since last time refresh DOES NOT exceed `cacheExpiredDuration`
-// use cached capabilities instead of refresh from cluster
-// else refresh from cluster and refresh the timestamp
-func useCacheInsteadRefresh(capDir string, cacheExpiredDuration time.Duration) (bool, error) {
- currentTimestamp := strconv.FormatInt(time.Now().Unix(), 10)
- tmpDir := filepath.Join(capDir, ".tmp")
- timeFilePath := filepath.Join(tmpDir, ".lasttimerefresh")
- exist, _ := system.CreateIfNotExist(tmpDir)
- if !exist {
- // file saving timestamp is not created yet, create and refresh the timestamp
- if err := ioutil.WriteFile(timeFilePath, []byte(currentTimestamp), 0600); err != nil {
- return false, err
- }
- return false, nil
- }
- r, err := ioutil.ReadFile(filepath.Clean(timeFilePath))
- if err != nil {
- if os.IsNotExist(err) {
- // tmpDir exists but `.lasttimerefresh` file doesn't
- if err := ioutil.WriteFile(timeFilePath, []byte(currentTimestamp), 0600); err != nil {
- return false, err
- }
- return false, nil
- }
- return false, err
- }
- i, err := strconv.ParseInt(string(r), 10, 64)
- if err != nil {
- return false, err
- }
- lt := time.Unix(i, 0)
- if time.Since(lt) > cacheExpiredDuration {
- // cache is expired, refresh the timestamp
- if err := ioutil.WriteFile(timeFilePath, []byte(currentTimestamp), 0600); err != nil {
- return false, err
- }
- return false, nil
- }
- // cache is not expired
- return true, nil
-}
-
-// each capability has a hash value cached in local capability dir
-// hash value is used to compare local capability with one from cluster
-// refresh report will show all changed capabilities
-func readCapDefHashFromLocal(capDir string) map[string]string {
- r := map[string]string{}
- tmpDir := filepath.Join(capDir, ".tmp")
- hashFilePath := filepath.Join(tmpDir, ".capabilityhash")
- if exist, err := system.CreateIfNotExist(tmpDir); !exist || err != nil {
- return r
- }
- if _, err := os.Stat(hashFilePath); os.IsNotExist(err) {
- return r
- }
- hashData, err := ioutil.ReadFile(filepath.Clean(hashFilePath))
- if err != nil {
- return r
- }
- if err := json.Unmarshal(hashData, &r); err != nil {
- return r
- }
- return r
-}
-
-func writeCapDefHashIntoLocal(capDir string, hashData map[string]string) error {
- tmpDir := filepath.Join(capDir, ".tmp")
- hashFilePath := filepath.Join(tmpDir, ".capabilityhash")
- if _, err := system.CreateIfNotExist(tmpDir); err != nil {
- return err
- }
- data, err := json.Marshal(hashData)
- if err != nil {
- return err
- }
- if err := ioutil.WriteFile(hashFilePath, data, 0600); err != nil {
- return err
- }
- return nil
-}
diff --git a/references/cli/refresh_test.go b/references/cli/refresh_test.go
deleted file mode 100644
index 4bbdc1b5b..000000000
--- a/references/cli/refresh_test.go
+++ /dev/null
@@ -1,49 +0,0 @@
-package cli
-
-import (
- "os"
- "testing"
- "time"
-
- "github.com/stretchr/testify/assert"
-)
-
-func TestCheckAndUpdateRefreshInterval(t *testing.T) {
- testdir := "testdir-refresh-interval"
- testMaxInterval := time.Second
-
- err := os.MkdirAll(testdir, 0755)
- assert.NoError(t, err)
- defer os.RemoveAll(testdir)
-
- r, err := useCacheInsteadRefresh(testdir, testMaxInterval)
- assert.Equal(t, r, false, "should not use cache for tmp file is not created")
- assert.NoError(t, err)
-
- r, err = useCacheInsteadRefresh(testdir, testMaxInterval)
- assert.Equal(t, r, true, "should use cache for interval is not expired")
- assert.NoError(t, err)
-
- time.Sleep(2 * testMaxInterval)
- r, err = useCacheInsteadRefresh(testdir, testMaxInterval)
- assert.Equal(t, r, false, "should not use cache for interval is already expired")
- assert.NoError(t, err)
-}
-
-func TestWriteAndReadLocalCapHash(t *testing.T) {
- testdir := "testdir-caphash"
- err := os.MkdirAll(testdir, 0755)
- assert.NoError(t, err)
- defer os.RemoveAll(testdir)
-
- result := readCapDefHashFromLocal(testdir)
- assert.Equal(t, result, map[string]string{}, "capability hash data should be empty")
- fakeHashData := map[string]string{
- "a": "test1",
- "b": "test2",
- }
- err = writeCapDefHashIntoLocal(testdir, fakeHashData)
- assert.NoError(t, err, "write new hash data successfully")
- result = readCapDefHashFromLocal(testdir)
- assert.Equal(t, result, fakeHashData, "read hash data successfully")
-}
diff --git a/references/cli/status.go b/references/cli/status.go
index 167853cac..3c9939403 100644
--- a/references/cli/status.go
+++ b/references/cli/status.go
@@ -92,11 +92,11 @@ func NewAppStatusCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Comma
ioStreams.Errorf("Error: failed to get Env: %s", err)
return err
}
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return err
}
- return printAppStatus(ctx, newClient, ioStreams, appName, env, cmd)
+ return printAppStatus(ctx, newClient, ioStreams, appName, env, cmd, c)
},
Annotations: map[string]string{
types.TagCommandType: types.TypeApp,
@@ -107,8 +107,8 @@ func NewAppStatusCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Comma
return cmd
}
-func printAppStatus(ctx context.Context, c client.Client, ioStreams cmdutil.IOStreams, appName string, env *types.EnvMeta, cmd *cobra.Command) error {
- app, err := appfile.LoadApplication(env.Name, appName)
+func printAppStatus(ctx context.Context, c client.Client, ioStreams cmdutil.IOStreams, appName string, env *types.EnvMeta, cmd *cobra.Command, velaC types.Args) error {
+ app, err := appfile.LoadApplication(env.Namespace, appName, velaC)
if err != nil {
return err
}
@@ -118,8 +118,7 @@ func printAppStatus(ctx context.Context, c client.Client, ioStreams cmdutil.IOSt
table := newUITable()
table.AddRow(" Name:", appName)
table.AddRow(" Namespace:", namespace)
- table.AddRow(" Created at:", app.CreateTime.String())
- table.AddRow(" Updated at:", app.UpdateTime.String())
+ table.AddRow(" Created at:", app.CreationTimestamp.String())
cmd.Printf("%s\n\n", table.String())
cmd.Printf("Services:\n\n")
@@ -216,14 +215,14 @@ HealthCheckLoop:
return healthStatus, healthInfo, nil
}
-func printTrackingDeployStatus(ctx context.Context, c client.Client, ioStreams cmdutil.IOStreams, compName, appName string, env *types.EnvMeta) (CompStatus, error) {
+func printTrackingDeployStatus(c types.Args, ioStreams cmdutil.IOStreams, appName string, env *types.EnvMeta) (CompStatus, error) {
sDeploy := newTrackingSpinnerWithDelay("Checking Status ...", trackingInterval)
sDeploy.Start()
defer sDeploy.Stop()
TrackDeployLoop:
for {
time.Sleep(trackingInterval)
- deployStatus, failMsg, err := TrackDeployStatus(ctx, c, compName, appName, env)
+ deployStatus, failMsg, err := TrackDeployStatus(c, appName, env)
if err != nil {
return compStatusUnknown, err
}
@@ -245,12 +244,12 @@ TrackDeployLoop:
}
// TrackDeployStatus will only check AppConfig is deployed successfully,
-func TrackDeployStatus(ctx context.Context, c client.Client, compName, appName string, env *types.EnvMeta) (CompStatus, string, error) {
- app, appObj, err := getApp(ctx, c, compName, appName, env)
+func TrackDeployStatus(c types.Args, appName string, env *types.EnvMeta) (CompStatus, string, error) {
+ appObj, err := appfile.LoadApplication(env.Namespace, appName, c)
if err != nil {
return compStatusUnknown, "", err
}
- if app == nil || appObj == nil {
+ if appObj == nil {
return compStatusUnknown, "", errors.New(ErrNotLoadAppConfig)
}
condition := appObj.Status.Conditions
@@ -319,25 +318,6 @@ func trackHealthCheckingStatus(ctx context.Context, c client.Client, compName, a
return compStatusHealthCheckDone, HealthStatusNotDiagnosed, "", nil
}
-func getApp(ctx context.Context, c client.Client, compName, appName string, env *types.EnvMeta) (*api.Application, *v1alpha2.Application, error) {
- var app *api.Application
- var err error
- if appName != "" {
- app, err = appfile.LoadApplication(env.Name, appName)
- } else {
- app, err = appfile.MatchAppByComp(env.Name, compName)
- }
- if err != nil {
- return nil, nil, err
- }
-
- appObj, err := appfile.GetApplication(ctx, c, app, env)
- if err != nil {
- return nil, nil, err
- }
- return app, appObj, nil
-}
-
func getWorkloadStatusFromApp(app *v1alpha2.Application, compName string) (v1alpha2.ApplicationComponentStatus, bool) {
foundWlStatus := false
wlStatus := v1alpha2.ApplicationComponentStatus{}
diff --git a/references/cli/system.go b/references/cli/system.go
index c684c7871..615cdebae 100644
--- a/references/cli/system.go
+++ b/references/cli/system.go
@@ -111,7 +111,7 @@ func NewInstallCommand(c types.Args, chartContent string, ioStreams cmdutil.IOSt
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return err
}
@@ -172,9 +172,6 @@ func (i *initCmd) run(ioStreams cmdutil.IOStreams, chartSource string) error {
"try running 'vela workloads' or 'vela traits' to check after a while, details: %v", err)
return nil
}
- if err := RefreshDefinitions(context.Background(), i.c, ioStreams, false, true); err != nil {
- return err
- }
ioStreams.Info("- Finished successfully.")
if waitDuration > 0 {
@@ -204,7 +201,7 @@ func CheckCapabilityReady(ctx context.Context, c types.Args, timeout time.Durati
defer spiner.Stop()
for {
- _, err = plugins.GetCapabilitiesFromCluster(ctx, types.DefaultKubeVelaNS, c, tmpdir, nil)
+ _, err = plugins.GetCapabilitiesFromCluster(ctx, types.DefaultKubeVelaNS, c, nil)
if err == nil {
return nil
}
diff --git a/references/cli/testdata/appfile.yaml b/references/cli/testdata/appfile.yaml
new file mode 100644
index 000000000..b9070263f
--- /dev/null
+++ b/references/cli/testdata/appfile.yaml
@@ -0,0 +1,18 @@
+name: first-vela-app
+services:
+ testsvc:
+ type: webservice
+ image: crccheck/hello-world
+ port: 8000
+ ingress:
+ domain: testsvc.example.com
+ http:
+ "/": 8000
+ abc:
+ type: webservice
+ image: crccheck/hello-world
+ port: 8000
+ ingress:
+ domain: testsvc.example.com
+ http:
+ "/": 8000
diff --git a/references/cli/traits.go b/references/cli/traits.go
index 8371aedd1..d9f606b69 100644
--- a/references/cli/traits.go
+++ b/references/cli/traits.go
@@ -1,7 +1,6 @@
package cli
import (
- "context"
"strings"
"github.com/spf13/cobra"
@@ -9,15 +8,13 @@ import (
"github.com/oam-dev/kubevela/apis/types"
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
"github.com/oam-dev/kubevela/references/common"
+ "github.com/oam-dev/kubevela/references/plugins"
)
// NewTraitsCommand creates `traits` command
func NewTraitsCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
- var workloadName string
- var enforceRefresh bool
- ctx := context.Background()
cmd := &cobra.Command{
- Use: "traits [--apply-to WORKLOAD_NAME]",
+ Use: "traits",
DisableFlagsInUseLine: true,
Short: "List traits",
Long: "List traits",
@@ -26,12 +23,11 @@ func NewTraitsCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
-
- if err := RefreshDefinitions(ctx, c, ioStreams, true, enforceRefresh); err != nil {
+ env, err := GetEnv(cmd)
+ if err != nil {
return err
}
-
- return printTraitList(&workloadName, ioStreams)
+ return printTraitList(env.Namespace, c, ioStreams)
},
Annotations: map[string]string{
types.TagCommandType: types.TypeCap,
@@ -39,22 +35,20 @@ func NewTraitsCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command
}
cmd.SetOut(ioStreams.Out)
- cmd.Flags().StringVar(&workloadName, "apply-to", "", "Workload name")
- cmd.Flags().BoolVarP(&enforceRefresh, "", "r", false, "Enforce refresh from cluster even if cache is not expired")
return cmd
}
-func printTraitList(workloadName *string, ioStreams cmdutil.IOStreams) error {
+func printTraitList(userNamespace string, c types.Args, ioStreams cmdutil.IOStreams) error {
table := newUITable()
- table.MaxColWidth = 120
table.Wrap = true
- traitDefinitionList, err := common.ListTraitDefinitions(workloadName)
+
+ traitDefinitionList, err := common.ListRawTraitDefinitions(userNamespace, c)
if err != nil {
return err
}
- table.AddRow("NAME", "DESCRIPTION", "APPLIES TO")
+ table.AddRow("NAME", "NAMESPACE", "APPLIES-TO", "CONFLICTS-WITH", "DESCRIPTION")
for _, t := range traitDefinitionList {
- table.AddRow(t.Name, t.Description, strings.Join(t.AppliesTo, "\n"))
+ table.AddRow(t.Name, t.Namespace, strings.Join(t.Spec.AppliesToWorkloads, ","), strings.Join(t.Spec.ConflictsWith, ","), plugins.GetDescription(t.Annotations))
}
ioStreams.Info(table.String())
return nil
diff --git a/references/cli/traits_test.go b/references/cli/traits_test.go
index 1fd06fd92..c50d9df5b 100644
--- a/references/cli/traits_test.go
+++ b/references/cli/traits_test.go
@@ -1,11 +1,9 @@
package cli
import (
- "bytes"
"os"
"testing"
- "github.com/gosuri/uitable"
"github.com/spf13/cobra"
"github.com/stretchr/testify/assert"
@@ -14,84 +12,6 @@ import (
"github.com/oam-dev/kubevela/references/common"
)
-func Test_printTraitList(t *testing.T) {
- traits := []types.Capability{
- {
- Name: "route",
- CrdName: "routes.oam.dev",
- // This format is currently OAM spec standard
- AppliesTo: []string{"apps/v1.Deployment", "alibaba/v1.Clonset"},
- },
- {
- Name: "scaler",
- CrdName: "scaler.oam.dev",
- // This format is also reasonable, it's align with oam definition name, so we also support here
- AppliesTo: []string{"deployments.apps"},
- },
- }
- workloads := []types.Capability{
- {
- Name: "deployment",
- CrdName: "deployments.apps",
- },
- {
- Name: "clonset",
- CrdName: "clonsets.alibaba",
- },
- }
- newTable := func() *uitable.Table {
- table := newUITable()
- table.AddRow("NAME", "DEFINITION", "APPLIES TO")
- return table
- }
- tb1 := newTable()
- tb1.AddRow("route", "routes.oam.dev", "deployment")
- tb1.AddRow("", "", "clonset")
- tb1.AddRow("scaler", "scaler.oam.dev", "deployment")
-
- tb2 := newTable()
- tb2.AddRow("route", "routes.oam.dev", "deployment")
- tb2.AddRow("scaler", "scaler.oam.dev", "deployment")
-
- tb3 := newTable()
- tb3.AddRow("route", "routes.oam.dev", "clonset")
-
- cases := map[string]struct {
- traits []types.Capability
- workloads []types.Capability
- workloadName string
- iostream cmdutil.IOStreams
- ExpectedString string
- }{
- "All Workloads": {
- traits: traits,
- workloads: workloads,
- ExpectedString: tb1.String() + "\n",
- },
- "Specify Workload Name deployment": {
- traits: traits,
- workloads: workloads,
- workloadName: "deployment",
- ExpectedString: tb2.String() + "\n",
- },
- "Specify Workload Name clonset": {
- traits: traits,
- workloads: workloads,
- workloadName: "clonset",
- ExpectedString: tb3.String() + "\n",
- },
- }
- // 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
- assert.NoError(t, printTraitList(&nn, iostream))
- }
-}
-
func TestNewTraitsCommandPersistentPreRunE(t *testing.T) {
io := cmdutil.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
fakeC := types.Args{}
diff --git a/references/cli/up.go b/references/cli/up.go
index 93c546e8a..01d505b12 100644
--- a/references/cli/up.go
+++ b/references/cli/up.go
@@ -2,7 +2,6 @@ package cli
import (
"github.com/spf13/cobra"
- "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/types"
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
@@ -31,7 +30,7 @@ func NewUpCommand(c types.Args, ioStream cmdutil.IOStreams) *cobra.Command {
if err != nil {
return err
}
- kubecli, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ kubecli, err := c.GetClient()
if err != nil {
return err
}
@@ -45,7 +44,7 @@ func NewUpCommand(c types.Args, ioStream cmdutil.IOStreams) *cobra.Command {
if err != nil {
return err
}
- return o.Run(filePath, c.Config)
+ return o.Run(filePath, velaEnv.Namespace, c)
},
}
cmd.SetOut(ioStream.Out)
diff --git a/references/cli/workloads.go b/references/cli/workloads.go
index 71f291e17..d1f82452f 100644
--- a/references/cli/workloads.go
+++ b/references/cli/workloads.go
@@ -1,19 +1,16 @@
package cli
import (
- "context"
-
"github.com/spf13/cobra"
"github.com/oam-dev/kubevela/apis/types"
cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
+ "github.com/oam-dev/kubevela/references/common"
"github.com/oam-dev/kubevela/references/plugins"
)
// NewWorkloadsCommand creates `workloads` command
func NewWorkloadsCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command {
- var enforceRefresh bool
- ctx := context.Background()
cmd := &cobra.Command{
Use: "workloads",
DisableFlagsInUseLine: true,
@@ -24,32 +21,29 @@ func NewWorkloadsCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Comma
return c.SetConfig()
},
RunE: func(cmd *cobra.Command, args []string) error {
-
- if err := RefreshDefinitions(ctx, c, ioStreams, true, enforceRefresh); err != nil {
- return err
- }
-
- workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
+ env, err := GetEnv(cmd)
if err != nil {
return err
}
- return printWorkloadList(workloads, ioStreams)
+ return printWorkloadList(env.Namespace, c, ioStreams)
},
Annotations: map[string]string{
types.TagCommandType: types.TypeCap,
},
}
cmd.SetOut(ioStreams.Out)
- cmd.Flags().BoolVarP(&enforceRefresh, "", "r", false, "Enforce refresh from cluster even if cache is not expired")
return cmd
}
-func printWorkloadList(workloadList []types.Capability, ioStreams cmdutil.IOStreams) error {
+func printWorkloadList(userNamespace string, c types.Args, ioStreams cmdutil.IOStreams) error {
+ def, err := common.ListRawWorkloadDefinitions(userNamespace, c)
+ if err != nil {
+ return err
+ }
table := newUITable()
- table.MaxColWidth = 120
- table.AddRow("NAME", "DESCRIPTION")
- for _, r := range workloadList {
- table.AddRow(r.Name, r.Description)
+ table.AddRow("NAME", "NAMESPACE", "WORKLOAD", "DESCRIPTION")
+ for _, r := range def {
+ table.AddRow(r.Name, r.Namespace, r.Spec.Reference.Name, plugins.GetDescription(r.Annotations))
}
ioStreams.Info(table.String())
return nil
diff --git a/references/common/application.go b/references/common/application.go
index e200c79d5..d22a35ee9 100644
--- a/references/common/application.go
+++ b/references/common/application.go
@@ -19,7 +19,6 @@ import (
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime/serializer/json"
apitypes "k8s.io/apimachinery/pkg/types"
- "k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client"
corev1alpha2 "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
@@ -95,6 +94,7 @@ type DeleteOptions struct {
CompName string
Client client.Client
Env *types.EnvMeta
+ C types.Args
}
// ListApplications lists all applications
@@ -224,19 +224,31 @@ func (o *DeleteOptions) DeleteApp() (string, error) {
return "", fmt.Errorf("delete application err: %w", err)
}
- // TODO(wonderflow): delete the default health scope here
+ for _, cmp := range app.Spec.Components {
+ healthScopeName, ok := cmp.Scopes[api.DefaultHealthScopeKey]
+ if ok {
+ var healthScope corev1alpha2.HealthScope
+ if err := o.Client.Get(ctx, client.ObjectKey{Namespace: o.Env.Namespace, Name: healthScopeName}, &healthScope); err != nil {
+ if apierrors.IsNotFound(err) {
+ continue
+ }
+ return "", fmt.Errorf("delete health scope %s err: %w", healthScopeName, err)
+ }
+ if err = o.Client.Delete(ctx, &healthScope); err != nil {
+ return "", fmt.Errorf("delete health scope %s err: %w", healthScopeName, err)
+ }
+ }
+ }
return fmt.Sprintf("app \"%s\" deleted from env \"%s\"", o.AppName, o.Env.Name), nil
}
// DeleteComponent will delete one component including server side.
func (o *DeleteOptions) DeleteComponent(io cmdutil.IOStreams) (string, error) {
- var app *api.Application
var err error
- if o.AppName != "" {
- app, err = appfile.LoadApplication(o.Env.Name, o.AppName)
- } else {
- app, err = appfile.MatchAppByComp(o.Env.Name, o.CompName)
+ if o.AppName == "" {
+ return "", errors.New("app name is required")
}
+ app, err := appfile.LoadApplication(o.Env.Namespace, o.AppName, o.C)
if err != nil {
return "", err
}
@@ -249,24 +261,15 @@ func (o *DeleteOptions) DeleteComponent(io cmdutil.IOStreams) (string, error) {
if err := appfile.RemoveComponent(app, o.CompName); err != nil {
return "", err
}
- if err := appfile.Save(app, o.Env.Name); err != nil {
- return "", err
- }
// Remove component from appConfig in k8s cluster
ctx := context.Background()
- if err := BuildRun(ctx, app, o.Client, o.Env, io); err != nil {
+
+ if err := o.Client.Update(ctx, app); err != nil {
return "", err
}
- // Remove component in k8s cluster
- var c corev1alpha2.Component
- c.Name = o.CompName
- c.Namespace = o.Env.Namespace
- err = o.Client.Delete(context.Background(), &c)
- if err != nil && !apierrors.IsNotFound(err) {
- return "", fmt.Errorf("delete component err: %w", err)
- }
+ // It's the server responsibility to GC component
return fmt.Sprintf("component \"%s\" deleted from \"%s\"", o.CompName, o.AppName), nil
}
@@ -359,8 +362,8 @@ func saveAndLoadRemoteAppfile(url string) (*api.AppFile, error) {
}
// ExportFromAppFile exports Application from appfile object
-func (o *AppfileOptions) ExportFromAppFile(app *api.AppFile, quiet bool) (*BuildResult, []byte, error) {
- tm, err := template.Load()
+func (o *AppfileOptions) ExportFromAppFile(app *api.AppFile, namespace string, quiet bool, c types.Args) (*BuildResult, []byte, error) {
+ tm, err := template.Load(namespace, c)
if err != nil {
return nil, nil, err
}
@@ -401,7 +404,7 @@ func (o *AppfileOptions) ExportFromAppFile(app *api.AppFile, quiet bool) (*Build
}
// Export export Application object from the path of Appfile
-func (o *AppfileOptions) Export(filePath string, quiet bool) (*BuildResult, []byte, error) {
+func (o *AppfileOptions) Export(filePath, namespace string, quiet bool, c types.Args) (*BuildResult, []byte, error) {
var app *api.AppFile
var err error
if !quiet {
@@ -410,9 +413,6 @@ func (o *AppfileOptions) Export(filePath string, quiet bool) (*BuildResult, []by
if filePath != "" {
if strings.HasPrefix(filePath, "https://") || strings.HasPrefix(filePath, "http://") {
app, err = saveAndLoadRemoteAppfile(filePath)
- if err != nil {
- return nil, nil, err
- }
} else {
app, err = api.LoadFromFile(filePath)
}
@@ -426,16 +426,16 @@ func (o *AppfileOptions) Export(filePath string, quiet bool) (*BuildResult, []by
if !quiet {
o.IO.Info("Load Template ...")
}
- return o.ExportFromAppFile(app, quiet)
+ return o.ExportFromAppFile(app, namespace, quiet, c)
}
// Run starts an application according to Appfile
-func (o *AppfileOptions) Run(filePath string, config *rest.Config) error {
- result, data, err := o.Export(filePath, false)
+func (o *AppfileOptions) Run(filePath, namespace string, c types.Args) error {
+ result, data, err := o.Export(filePath, namespace, false, c)
if err != nil {
return err
}
- dm, err := discoverymapper.New(config)
+ dm, err := discoverymapper.New(c.Config)
if err != nil {
return err
}
diff --git a/references/common/capability.go b/references/common/capability.go
index 2c4e57062..a412a14e4 100644
--- a/references/common/capability.go
+++ b/references/common/capability.go
@@ -259,9 +259,9 @@ func SyncCapabilityCenter(capabilityCenterName string) error {
// RemoveCapabilityFromCluster will remove a capability from cluster.
// 1. remove definition 2. uninstall chart 3. remove local files
-func RemoveCapabilityFromCluster(client client.Client, capabilityName string) (string, error) {
+func RemoveCapabilityFromCluster(userNamespace string, c types.Args, client client.Client, capabilityName string) (string, error) {
ioStreams := cmdutil.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
- if err := RemoveCapability(client, capabilityName, ioStreams); err != nil {
+ if err := RemoveCapability(userNamespace, c, client, capabilityName, ioStreams); err != nil {
return "", err
}
msg := fmt.Sprintf("%s removed successfully", capabilityName)
@@ -270,9 +270,9 @@ func RemoveCapabilityFromCluster(client client.Client, capabilityName string) (s
// RemoveCapability will remove a capability from cluster.
// 1. remove definition 2. uninstall chart 3. remove local files
-func RemoveCapability(client client.Client, capabilityName string, ioStreams cmdutil.IOStreams) error {
+func RemoveCapability(userNamespace string, c types.Args, client client.Client, capabilityName string, ioStreams cmdutil.IOStreams) error {
// TODO(wonderflow): make sure no apps is using this capability
- caps, err := plugins.LoadAllInstalledCapability()
+ caps, err := plugins.LoadAllInstalledCapability(userNamespace, c)
if err != nil {
return err
}
@@ -329,14 +329,14 @@ func uninstallCap(client client.Client, cap types.Capability, ioStreams cmdutil.
}
// ListCapabilities will list all caps from specified center
-func ListCapabilities(capabilityCenterName string) ([]types.Capability, error) {
+func ListCapabilities(userNamespace string, c types.Args, capabilityCenterName string) ([]types.Capability, error) {
var capabilityList []types.Capability
dir, err := system.GetCapCenterDir()
if err != nil {
return capabilityList, err
}
if capabilityCenterName != "" {
- return listCenterCapabilities(filepath.Join(dir, capabilityCenterName))
+ return listCenterCapabilities(userNamespace, c, filepath.Join(dir, capabilityCenterName))
}
dirs, err := ioutil.ReadDir(dir)
if err != nil {
@@ -346,7 +346,7 @@ func ListCapabilities(capabilityCenterName string) ([]types.Capability, error) {
if !dd.IsDir() {
continue
}
- caps, err := listCenterCapabilities(filepath.Join(dir, dd.Name()))
+ caps, err := listCenterCapabilities(userNamespace, c, filepath.Join(dir, dd.Name()))
if err != nil {
return capabilityList, err
}
@@ -355,7 +355,7 @@ func ListCapabilities(capabilityCenterName string) ([]types.Capability, error) {
return capabilityList, nil
}
-func listCenterCapabilities(repoDir string) ([]types.Capability, error) {
+func listCenterCapabilities(userNamespace string, c types.Args, repoDir string) ([]types.Capability, error) {
templates, err := plugins.LoadCapabilityFromSyncedCenter(repoDir)
if err != nil {
return templates, err
@@ -364,9 +364,9 @@ func listCenterCapabilities(repoDir string) ([]types.Capability, error) {
return templates, nil
}
baseDir := filepath.Base(repoDir)
- workloads := gatherWorkloads(templates)
+ workloads := gatherWorkloads(userNamespace, c, templates)
for i, p := range templates {
- status := checkInstallStatus(baseDir, p)
+ status := checkInstallStatus(userNamespace, c, baseDir, p)
convertedApplyTo := ConvertApplyTo(p.AppliesTo, workloads)
templates[i].Center = baseDir
templates[i].Status = status
@@ -409,8 +409,8 @@ func RemoveCapabilityCenter(centerName string) (string, error) {
return message, err
}
-func gatherWorkloads(templates []types.Capability) []types.Capability {
- workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
+func gatherWorkloads(userNamespace string, c types.Args, templates []types.Capability) []types.Capability {
+ workloads, err := plugins.LoadInstalledCapabilityWithType(userNamespace, c, types.TypeWorkload)
if err != nil {
workloads = make([]types.Capability, 0)
}
@@ -422,9 +422,9 @@ func gatherWorkloads(templates []types.Capability) []types.Capability {
return workloads
}
-func checkInstallStatus(repoName string, tmp types.Capability) string {
+func checkInstallStatus(userNamespace string, c types.Args, repoName string, tmp types.Capability) string {
var status = "uninstalled"
- installed, _ := plugins.LoadInstalledCapabilityWithType(tmp.Type)
+ installed, _ := plugins.LoadInstalledCapabilityWithType(userNamespace, c, tmp.Type)
for _, i := range installed {
if i.Source != nil && i.Source.RepoName == repoName && i.Name == tmp.Name && i.CrdName == tmp.CrdName {
return "installed"
diff --git a/references/common/trait.go b/references/common/trait.go
index 704c3aa42..5ed3d9cd4 100644
--- a/references/common/trait.go
+++ b/references/common/trait.go
@@ -5,45 +5,79 @@ import (
"fmt"
"strings"
- "cuelang.org/go/cue"
plur "github.com/gertd/go-pluralize"
- "github.com/spf13/pflag"
- "sigs.k8s.io/controller-runtime/pkg/client"
+ client2 "sigs.k8s.io/controller-runtime/pkg/client"
+ "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/types"
- cmdutil "github.com/oam-dev/kubevela/pkg/utils/util"
- "github.com/oam-dev/kubevela/references/appfile"
- "github.com/oam-dev/kubevela/references/appfile/api"
+ "github.com/oam-dev/kubevela/pkg/oam"
+ "github.com/oam-dev/kubevela/pkg/oam/util"
"github.com/oam-dev/kubevela/references/plugins"
)
// ListTraitDefinitions will list all definition include traits and workloads
-func ListTraitDefinitions(workloadName *string) ([]types.Capability, error) {
+func ListTraitDefinitions(userNamespace string, c types.Args, workloadName *string) ([]types.Capability, error) {
var traitList []types.Capability
- traits, err := plugins.LoadInstalledCapabilityWithType(types.TypeTrait)
+ traits, err := plugins.LoadInstalledCapabilityWithType(userNamespace, c, types.TypeTrait)
if err != nil {
return traitList, err
}
- workloads, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
+ workloads, err := plugins.LoadInstalledCapabilityWithType(userNamespace, c, types.TypeWorkload)
if err != nil {
return traitList, err
}
- traitList = convertAllAppliyToList(traits, workloads, workloadName)
+ traitList = convertAllApplyToList(traits, workloads, workloadName)
return traitList, nil
}
+// ListRawTraitDefinitions will list raw definition
+func ListRawTraitDefinitions(userNamespace string, c types.Args) ([]v1alpha2.TraitDefinition, error) {
+ client, err := c.GetClient()
+ if err != nil {
+ return nil, err
+ }
+ ctx := util.SetNamespaceInCtx(context.Background(), userNamespace)
+ traitList := v1alpha2.TraitDefinitionList{}
+ if err = client.List(ctx, &traitList, client2.InNamespace(userNamespace)); err != nil {
+ return nil, err
+ }
+ sysTraitList := v1alpha2.TraitDefinitionList{}
+ if err = client.List(ctx, &sysTraitList, client2.InNamespace(oam.SystemDefinitonNamespace)); err != nil {
+ return nil, err
+ }
+ return append(traitList.Items, sysTraitList.Items...), nil
+}
+
+// ListRawWorkloadDefinitions will list raw definition
+func ListRawWorkloadDefinitions(userNamespace string, c types.Args) ([]v1alpha2.WorkloadDefinition, error) {
+ client, err := c.GetClient()
+ if err != nil {
+ return nil, err
+ }
+ ctx := util.SetNamespaceInCtx(context.Background(), userNamespace)
+ workloadList := v1alpha2.WorkloadDefinitionList{}
+ if err = client.List(ctx, &workloadList); err != nil {
+ return nil, err
+ }
+ sysWorkloadList := v1alpha2.WorkloadDefinitionList{}
+ if err = client.List(ctx, &sysWorkloadList, client2.InNamespace(oam.SystemDefinitonNamespace)); err != nil {
+ return nil, err
+ }
+ return append(workloadList.Items, sysWorkloadList.Items...), nil
+}
+
// GetTraitDefinition will get trait capability with applyTo converted
-func GetTraitDefinition(workloadName *string, traitType string) (types.Capability, error) {
+func GetTraitDefinition(userNamespace string, c types.Args, workloadName *string, traitType string) (types.Capability, error) {
var traitDef types.Capability
traitCap, err := plugins.GetInstalledCapabilityWithCapName(types.TypeTrait, traitType)
if err != nil {
return traitDef, err
}
- workloadsCap, err := plugins.LoadInstalledCapabilityWithType(types.TypeWorkload)
+ workloadsCap, err := plugins.LoadInstalledCapabilityWithType(userNamespace, c, types.TypeWorkload)
if err != nil {
return traitDef, err
}
- traitList := convertAllAppliyToList([]types.Capability{traitCap}, workloadsCap, workloadName)
+ traitList := convertAllApplyToList([]types.Capability{traitCap}, workloadsCap, workloadName)
if len(traitList) != 1 {
return traitDef, fmt.Errorf("could not get installed capability by %s", traitType)
}
@@ -51,7 +85,7 @@ func GetTraitDefinition(workloadName *string, traitType string) (types.Capabilit
return traitDef, nil
}
-func convertAllAppliyToList(traits []types.Capability, workloads []types.Capability, workloadName *string) []types.Capability {
+func convertAllApplyToList(traits []types.Capability, workloads []types.Capability, workloadName *string) []types.Capability {
var traitList []types.Capability
for _, t := range traits {
convertedApplyTo := ConvertApplyTo(t.AppliesTo, workloads)
@@ -118,112 +152,3 @@ func Parse(applyTo string) string {
}
return plur.NewClient().Plural(strings.ToLower(l[1])) + "." + apigroup
}
-
-// ValidateAndMutateForCore was built in validate and mutate function for core workloads and traits
-func ValidateAndMutateForCore(traitType, workloadName string, flags *pflag.FlagSet, env *types.EnvMeta) error {
- switch traitType {
- case "route":
- domain, _ := flags.GetString("domain")
- if domain == "" {
- if env.Domain == "" {
- return fmt.Errorf("--domain is required if not contain in environment")
- }
- if strings.HasPrefix(env.Domain, "https://") {
- env.Domain = strings.TrimPrefix(env.Domain, "https://")
- }
- if strings.HasPrefix(env.Domain, "http://") {
- env.Domain = strings.TrimPrefix(env.Domain, "http://")
- }
- if err := flags.Set("domain", workloadName+"."+env.Domain); err != nil {
- return fmt.Errorf("set flag for vela-core trait('route') err %w, please make sure your template is right", err)
- }
- }
- issuer, _ := flags.GetString("issuer")
- if issuer == "" && env.Issuer != "" {
- if err := flags.Set("issuer", env.Issuer); err != nil {
- return fmt.Errorf("set flag for vela-core trait('route') err %w, please make sure your template is right", err)
- }
- }
- default:
- // extend other trait here in the future
- }
- return nil
-}
-
-// AddOrUpdateTrait attach trait to workload
-func AddOrUpdateTrait(env *types.EnvMeta, appName string, componentName string, flagSet *pflag.FlagSet, template types.Capability) (*api.Application, error) {
- err := ValidateAndMutateForCore(template.Name, componentName, flagSet, env)
- if err != nil {
- return nil, err
- }
- if appName == "" {
- appName = componentName
- }
- app, err := appfile.LoadApplication(env.Name, appName)
- if err != nil {
- return app, err
- }
- traitAlias := template.Name
- traitData, err := appfile.GetTraitsByType(app, componentName, traitAlias)
- if err != nil {
- return app, err
- }
- for _, v := range template.Parameters {
- name := v.Name
- if v.Alias != "" {
- name = v.Alias
- }
- // nolint:exhaustive
- switch v.Type {
- case cue.IntKind:
- traitData[v.Name], err = flagSet.GetInt64(name)
- case cue.StringKind:
- traitData[v.Name], err = flagSet.GetString(name)
- case cue.BoolKind:
- traitData[v.Name], err = flagSet.GetBool(name)
- case cue.NumberKind, cue.FloatKind:
- traitData[v.Name], err = flagSet.GetFloat64(name)
- default:
- // Currently we don't support get value from complex type
- continue
- }
-
- if err != nil {
- return nil, fmt.Errorf("get flag(s) \"%s\" err %w", name, err)
- }
- }
- if err = appfile.SetTrait(app, componentName, traitAlias, traitData); err != nil {
- return app, err
- }
- return app, appfile.Save(app, env.Name)
-}
-
-// TraitOperationRun will check if it's a stage operation before run
-func TraitOperationRun(ctx context.Context, c client.Client, env *types.EnvMeta, appObj *api.Application,
- staging bool, io cmdutil.IOStreams) (string, error) {
- if staging {
- return "Staging saved", nil
- }
- err := BuildRun(ctx, appObj, c, env, io)
- if err != nil {
- return "", err
- }
- return "Deployed!", nil
-}
-
-// PrepareDetachTrait will detach trait in local AppFile
-func PrepareDetachTrait(envName string, traitType string, componentName string, appName string) (*api.Application, error) {
- var appObj *api.Application
- var err error
- if appName == "" {
- appName = componentName
- }
- if appObj, err = appfile.LoadApplication(envName, appName); err != nil {
- return appObj, err
- }
-
- if err = appfile.RemoveTrait(appObj, componentName, traitType); err != nil {
- return appObj, err
- }
- return appObj, appfile.Save(appObj, envName)
-}
diff --git a/references/common/workload.go b/references/common/workload.go
index 9cde486fa..3eca9cde9 100644
--- a/references/common/workload.go
+++ b/references/common/workload.go
@@ -1,7 +1,6 @@
package common
import (
- "context"
"fmt"
"strconv"
"strings"
@@ -28,27 +27,20 @@ type RunOptions struct {
util.IOStreams
}
-// LoadIfExist will load Application from local dir
-func LoadIfExist(envName string, workloadName string, appGroup string) (*api.Application, error) {
+// InitApplication will load Application from cluster
+func InitApplication(env *types.EnvMeta, c types.Args, workloadName string, appGroup string) (*api.Application, error) {
var appName string
if appGroup != "" {
appName = appGroup
} else {
appName = workloadName
}
- app, err := appfile.LoadApplication(envName, appName)
-
- // can't handle
- if err != nil && !appfile.IsNotFound(appName, err) {
- return nil, err
- }
-
+ // TODO(wonderflow): we should load the existing application from cluster and convert to appfile
+ // app, err := appfile.LoadApplication(env.Namespace, appName, c)
// compatible application not found
- if app == nil {
- app, err = appfile.NewEmptyApplication()
- if err != nil {
- return nil, err
- }
+ app, err := appfile.NewEmptyApplication(env.Namespace, c)
+ if err != nil {
+ return nil, err
}
app.Name = appName
@@ -56,8 +48,8 @@ func LoadIfExist(envName string, workloadName string, appGroup string) (*api.App
}
// BaseComplete will construct an Application from cli parameters.
-func BaseComplete(envName string, workloadName string, appName string, flagSet *pflag.FlagSet, workloadType string) (*api.Application, error) {
- app, err := LoadIfExist(envName, workloadName, appName)
+func BaseComplete(env *types.EnvMeta, c types.Args, workloadName string, appName string, flagSet *pflag.FlagSet, workloadType string) (*api.Application, error) {
+ app, err := InitApplication(env, c, workloadName, appName)
if err != nil {
return nil, err
}
@@ -69,7 +61,7 @@ func BaseComplete(envName string, workloadName string, appName string, flagSet *
// Not exist
tp = workloadType
}
- template, err := plugins.LoadCapabilityByName(tp)
+ template, err := plugins.LoadCapabilityByName(tp, env.Namespace, c)
if err != nil {
return nil, err
}
@@ -129,17 +121,5 @@ func BaseComplete(envName string, workloadName string, appName string, flagSet *
if err = appfile.SetWorkload(app, workloadName, tp, workloadData); err != nil {
return app, err
}
- return app, appfile.Save(app, envName)
-}
-
-// BaseRun will check if it's a stating operation before run
-func BaseRun(staging bool, app *api.Application, kubeClient client.Client, env *types.EnvMeta, io util.IOStreams) (string, error) {
- if staging {
- return "Staging saved", nil
- }
- if err := BuildRun(context.Background(), app, kubeClient, env, io); err != nil {
- err = fmt.Errorf("create app err: %w", err)
- return "", err
- }
- return fmt.Sprintf("App %s deployed", app.Name), nil
+ return app, appfile.Save(app, env.Name)
}
diff --git a/references/plugins/capcenter.go b/references/plugins/capcenter.go
index f28f2197b..cf9a0bbe3 100644
--- a/references/plugins/capcenter.go
+++ b/references/plugins/capcenter.go
@@ -162,7 +162,7 @@ func StoreRepos(repos []CapCenterConfig) error {
}
// ParseAndSyncCapability will convert config from remote center to capability
-func ParseAndSyncCapability(data []byte, syncDir string) (types.Capability, error) {
+func ParseAndSyncCapability(data []byte) (types.Capability, error) {
var obj = unstructured.Unstructured{Object: make(map[string]interface{})}
err := yaml.Unmarshal(data, &obj.Object)
if err != nil {
@@ -175,14 +175,14 @@ func ParseAndSyncCapability(data []byte, syncDir string) (types.Capability, erro
if err != nil {
return types.Capability{}, err
}
- return HandleDefinition(rd.Name, syncDir, rd.Spec.Reference.Name, rd.Annotations, rd.Spec.Extension, types.TypeWorkload, nil, rd.Spec.Schematic)
+ return HandleDefinition(rd.Name, rd.Spec.Reference.Name, rd.Annotations, rd.Spec.Extension, types.TypeWorkload, nil, rd.Spec.Schematic)
case "TraitDefinition":
var td v1alpha2.TraitDefinition
err = yaml.Unmarshal(data, &td)
if err != nil {
return types.Capability{}, err
}
- return HandleDefinition(td.Name, syncDir, 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.Spec.Extension, types.TypeTrait, td.Spec.AppliesToWorkloads, td.Spec.Schematic)
case "ScopeDefinition":
// TODO(wonderflow): support scope definition here.
}
@@ -241,7 +241,7 @@ func (g *GithubCenter) SyncCapabilityFromCenter() error {
return fmt.Errorf("decode github content %s err %w", *fileContent.Path, err)
}
}
- tmp, err := ParseAndSyncCapability(data, filepath.Join(dir, ".tmp"))
+ tmp, err := ParseAndSyncCapability(data)
if err != nil {
fmt.Printf("parse definition of %s err %v\n", *fileContent.Name, err)
continue
diff --git a/references/plugins/cluster.go b/references/plugins/cluster.go
index e1dbad075..e9b192e20 100644
--- a/references/plugins/cluster.go
+++ b/references/plugins/cluster.go
@@ -3,9 +3,7 @@ package plugins
import (
"context"
"fmt"
- "io/ioutil"
"os"
- "path/filepath"
"strings"
"github.com/pkg/errors"
@@ -20,7 +18,6 @@ import (
"github.com/oam-dev/kubevela/pkg/oam/util"
"github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/pkg/utils/helm"
- "github.com/oam-dev/kubevela/pkg/utils/system"
util2 "github.com/oam-dev/kubevela/pkg/utils/util"
)
@@ -28,12 +25,12 @@ import (
const DescriptionUndefined = "description not defined"
// GetCapabilitiesFromCluster will get capability from K8s cluster
-func GetCapabilitiesFromCluster(ctx context.Context, namespace string, c types.Args, syncDir string, selector labels.Selector) ([]types.Capability, error) {
- workloads, _, err := GetWorkloadsFromCluster(ctx, namespace, c, syncDir, selector)
+func GetCapabilitiesFromCluster(ctx context.Context, namespace string, c types.Args, selector labels.Selector) ([]types.Capability, error) {
+ workloads, _, err := GetWorkloadsFromCluster(ctx, namespace, c, selector)
if err != nil {
return nil, err
}
- traits, _, err := GetTraitsFromCluster(ctx, namespace, c, syncDir, selector)
+ traits, _, err := GetTraitsFromCluster(ctx, namespace, c, selector)
if err != nil {
return nil, err
}
@@ -42,8 +39,8 @@ func GetCapabilitiesFromCluster(ctx context.Context, namespace string, c types.A
}
// GetWorkloadsFromCluster will get capability from K8s cluster
-func GetWorkloadsFromCluster(ctx context.Context, namespace string, c types.Args, syncDir string, selector labels.Selector) ([]types.Capability, []error, error) {
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+func GetWorkloadsFromCluster(ctx context.Context, namespace string, c types.Args, selector labels.Selector) ([]types.Capability, []error, error) {
+ newClient, err := c.GetClient()
if err != nil {
return nil, nil, err
}
@@ -61,11 +58,12 @@ func GetWorkloadsFromCluster(ctx context.Context, namespace string, c types.Args
var templateErrors []error
for _, wd := range workloadDefs.Items {
- tmp, err := HandleDefinition(wd.Name, syncDir, wd.Spec.Reference.Name, wd.Annotations, wd.Spec.Extension, types.TypeWorkload, nil, wd.Spec.Schematic)
+ tmp, err := HandleDefinition(wd.Name, wd.Spec.Reference.Name, wd.Annotations, wd.Spec.Extension, types.TypeWorkload, nil, wd.Spec.Schematic)
if err != nil {
templateErrors = append(templateErrors, errors.Wrapf(err, "handle workload template `%s` failed", wd.Name))
continue
}
+ tmp.Namespace = namespace
if tmp, err = validateCapabilities(tmp, dm, wd.Name, wd.Spec.Reference); err != nil {
return nil, nil, err
}
@@ -75,8 +73,8 @@ func GetWorkloadsFromCluster(ctx context.Context, namespace string, c types.Args
}
// GetTraitsFromCluster will get capability from K8s cluster
-func GetTraitsFromCluster(ctx context.Context, namespace string, c types.Args, syncDir string, selector labels.Selector) ([]types.Capability, []error, error) {
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+func GetTraitsFromCluster(ctx context.Context, namespace string, c types.Args, selector labels.Selector) ([]types.Capability, []error, error) {
+ newClient, err := c.GetClient()
if err != nil {
return nil, nil, err
}
@@ -93,11 +91,12 @@ func GetTraitsFromCluster(ctx context.Context, namespace string, c types.Args, s
var templateErrors []error
for _, td := range traitDefs.Items {
- tmp, err := HandleDefinition(td.Name, syncDir, td.Spec.Reference.Name, td.Annotations, td.Spec.Extension, types.TypeTrait, td.Spec.AppliesToWorkloads, td.Spec.Schematic)
+ tmp, err := HandleDefinition(td.Name, td.Spec.Reference.Name, td.Annotations, td.Spec.Extension, types.TypeTrait, td.Spec.AppliesToWorkloads, td.Spec.Schematic)
if err != nil {
templateErrors = append(templateErrors, errors.Wrapf(err, "handle trait template `%s` failed", td.Name))
continue
}
+ tmp.Namespace = namespace
if tmp, err = validateCapabilities(tmp, dm, td.Name, td.Spec.Reference); err != nil {
return nil, nil, err
}
@@ -134,9 +133,9 @@ func validateCapabilities(tmp types.Capability, dm discoverymapper.DiscoveryMapp
}
// HandleDefinition will handle definition to capability
-func HandleDefinition(name, syncDir, crdName string, annotation map[string]string, extension *runtime.RawExtension, tp types.CapType, applyTo []string, schematic *corev1alpha2.Schematic) (types.Capability, error) {
+func HandleDefinition(name, crdName string, annotation map[string]string, extension *runtime.RawExtension, tp types.CapType, applyTo []string, schematic *corev1alpha2.Schematic) (types.Capability, error) {
var tmp types.Capability
- tmp, err := HandleTemplate(extension, schematic, name, syncDir)
+ tmp, err := HandleTemplate(extension, schematic, name)
if err != nil {
return types.Capability{}, err
}
@@ -158,11 +157,12 @@ func GetDescription(annotation map[string]string) string {
if !ok {
return DescriptionUndefined
}
+ desc = strings.ReplaceAll(desc, "\n", " ")
return desc
}
// HandleTemplate will handle definition template to capability
-func HandleTemplate(in *runtime.RawExtension, schematic *corev1alpha2.Schematic, name, syncDir string) (types.Capability, error) {
+func HandleTemplate(in *runtime.RawExtension, schematic *corev1alpha2.Schematic, name string) (types.Capability, error) {
tmp, err := util.ConvertTemplateJSON2Object(name, in, schematic)
if err != nil {
return types.Capability{}, err
@@ -183,15 +183,10 @@ func HandleTemplate(in *runtime.RawExtension, schematic *corev1alpha2.Schematic,
if tmp.CueTemplate == "" {
return types.Capability{}, errors.New("template not exist in definition")
}
- _, _ = system.CreateIfNotExist(syncDir)
- filePath := filepath.Join(syncDir, name+".cue")
- //nolint:gosec
- err = ioutil.WriteFile(filePath, []byte(tmp.CueTemplate), 0644)
if err != nil {
return types.Capability{}, err
}
- tmp.DefinitionPath = filePath
- tmp.Parameters, err = cue.GetParameters(filePath)
+ tmp.Parameters, err = cue.GetParameters(tmp.CueTemplate)
if err != nil {
return types.Capability{}, err
}
@@ -203,7 +198,7 @@ func SyncDefinitionsToLocal(ctx context.Context, c types.Args, localDefinitionDi
var syncedTemplates []types.Capability
var warnings []string
- templates, templateErrors, err := GetWorkloadsFromCluster(ctx, types.DefaultKubeVelaNS, c, localDefinitionDir, nil)
+ templates, templateErrors, err := GetWorkloadsFromCluster(ctx, types.DefaultKubeVelaNS, c, nil)
if err != nil {
return nil, nil, err
}
@@ -215,7 +210,7 @@ func SyncDefinitionsToLocal(ctx context.Context, c types.Args, localDefinitionDi
syncedTemplates = append(syncedTemplates, templates...)
SinkTemp2Local(templates, localDefinitionDir)
- templates, templateErrors, err = GetTraitsFromCluster(ctx, types.DefaultKubeVelaNS, c, localDefinitionDir, nil)
+ templates, templateErrors, err = GetTraitsFromCluster(ctx, types.DefaultKubeVelaNS, c, nil)
if err != nil {
return nil, warnings, err
}
@@ -233,7 +228,7 @@ func SyncDefinitionsToLocal(ctx context.Context, c types.Args, localDefinitionDi
func SyncDefinitionToLocal(ctx context.Context, c types.Args, localDefinitionDir string, capabilityName string) (*types.Capability, error) {
var foundCapability bool
- newClient, err := client.New(c.Config, client.Options{Scheme: c.Schema})
+ newClient, err := c.GetClient()
if err != nil {
return nil, err
}
@@ -244,7 +239,7 @@ func SyncDefinitionToLocal(ctx context.Context, c types.Args, localDefinitionDir
foundCapability = true
}
if foundCapability {
- template, err := HandleDefinition(capabilityName, localDefinitionDir, workloadDef.Spec.Reference.Name,
+ template, err := HandleDefinition(capabilityName, workloadDef.Spec.Reference.Name,
workloadDef.Annotations, workloadDef.Spec.Extension, types.TypeWorkload, nil, workloadDef.Spec.Schematic)
if err == nil {
return &template, nil
@@ -258,7 +253,7 @@ func SyncDefinitionToLocal(ctx context.Context, c types.Args, localDefinitionDir
foundCapability = true
}
if foundCapability {
- template, err := HandleDefinition(capabilityName, localDefinitionDir, traitDef.Spec.Reference.Name,
+ template, err := HandleDefinition(capabilityName, traitDef.Spec.Reference.Name,
traitDef.Annotations, traitDef.Spec.Extension, types.TypeTrait, nil, workloadDef.Spec.Schematic)
if err == nil {
return &template, nil
diff --git a/references/plugins/cluster_test.go b/references/plugins/cluster_test.go
index 2ee1cedcb..3d99a467d 100644
--- a/references/plugins/cluster_test.go
+++ b/references/plugins/cluster_test.go
@@ -108,7 +108,7 @@ var _ = Describe("DefinitionFiles", func() {
// Notice!! DefinitionPath Object is Cluster Scope object
// which means objects created in other DefinitionNamespace will also affect here.
It("gettrait", func() {
- traitDefs, _, err := GetTraitsFromCluster(context.Background(), DefinitionNamespace, types.Args{Config: cfg, Schema: scheme}, definitionDir, selector)
+ traitDefs, _, err := GetTraitsFromCluster(context.Background(), DefinitionNamespace, types.Args{Config: cfg, Schema: scheme}, selector)
Expect(err).Should(BeNil())
logf.Log.Info(fmt.Sprintf("Getting trait definitions %v", traitDefs))
for i := range traitDefs {
@@ -116,7 +116,6 @@ var _ = Describe("DefinitionFiles", func() {
By("check CueTemplate is fulfilled")
Expect(traitDefs[i].CueTemplate).ShouldNot(BeEmpty())
traitDefs[i].CueTemplate = ""
- traitDefs[i].DefinitionPath = ""
}
Expect(traitDefs).Should(Equal([]types.Capability{route}))
})
@@ -124,7 +123,7 @@ var _ = Describe("DefinitionFiles", func() {
// Notice!! DefinitionPath Object is Cluster Scope object
// which means objects created in other DefinitionNamespace will also affect here.
It("getworkload", func() {
- workloadDefs, _, err := GetWorkloadsFromCluster(context.Background(), DefinitionNamespace, types.Args{Config: cfg, Schema: scheme}, definitionDir, selector)
+ workloadDefs, _, err := GetWorkloadsFromCluster(context.Background(), DefinitionNamespace, types.Args{Config: cfg, Schema: scheme}, selector)
Expect(err).Should(BeNil())
logf.Log.Info(fmt.Sprintf("Getting workload definitions %v", workloadDefs))
for i := range workloadDefs {
@@ -132,17 +131,15 @@ var _ = Describe("DefinitionFiles", func() {
By("check CueTemplate is fulfilled")
Expect(workloadDefs[i].CueTemplate).ShouldNot(BeEmpty())
workloadDefs[i].CueTemplate = ""
- workloadDefs[i].DefinitionPath = ""
}
Expect(workloadDefs).Should(Equal([]types.Capability{deployment, websvc}))
})
It("getall", func() {
- alldef, err := GetCapabilitiesFromCluster(context.Background(), DefinitionNamespace, types.Args{Config: cfg, Schema: scheme}, definitionDir, selector)
+ alldef, err := GetCapabilitiesFromCluster(context.Background(), DefinitionNamespace, types.Args{Config: cfg, Schema: scheme}, selector)
Expect(err).Should(BeNil())
logf.Log.Info(fmt.Sprintf("Getting all definitions %v", alldef))
for i := range alldef {
alldef[i].CueTemplate = ""
- alldef[i].DefinitionPath = ""
}
Expect(alldef).Should(Equal([]types.Capability{deployment, websvc, route}))
})
diff --git a/references/plugins/local.go b/references/plugins/local.go
index 06504f926..53fca848e 100644
--- a/references/plugins/local.go
+++ b/references/plugins/local.go
@@ -2,6 +2,7 @@ package plugins
import (
"bytes"
+ "context"
"encoding/json"
"fmt"
"io/ioutil"
@@ -14,8 +15,8 @@ import (
)
// LoadCapabilityByName will load capability from local by name
-func LoadCapabilityByName(name string) (types.Capability, error) {
- caps, err := LoadAllInstalledCapability()
+func LoadCapabilityByName(name string, userNamespace string, c types.Args) (types.Capability, error) {
+ caps, err := LoadAllInstalledCapability(userNamespace, c)
if err != nil {
return types.Capability{}, err
}
@@ -28,26 +29,49 @@ func LoadCapabilityByName(name string) (types.Capability, error) {
}
// LoadAllInstalledCapability will list all capability
-func LoadAllInstalledCapability() ([]types.Capability, error) {
- workloads, err := LoadInstalledCapabilityWithType(types.TypeWorkload)
+func LoadAllInstalledCapability(userNamespace string, c types.Args) ([]types.Capability, error) {
+ caps, err := GetCapabilitiesFromCluster(context.TODO(), userNamespace, c, nil)
if err != nil {
return nil, err
}
- traits, err := LoadInstalledCapabilityWithType(types.TypeTrait)
+ systemCaps, err := GetCapabilitiesFromCluster(context.TODO(), types.DefaultKubeVelaNS, c, nil)
if err != nil {
return nil, err
}
- workloads = append(workloads, traits...)
- return workloads, nil
+ caps = append(caps, systemCaps...)
+ return caps, nil
}
// LoadInstalledCapabilityWithType will load cap list by type
-func LoadInstalledCapabilityWithType(capT types.CapType) ([]types.Capability, error) {
- dir, err := system.GetCapabilityDir()
- if err != nil {
- return nil, err
+func LoadInstalledCapabilityWithType(userNamespace string, c types.Args, capT types.CapType) ([]types.Capability, error) {
+ switch capT {
+ case types.TypeWorkload:
+ caps, _, err := GetWorkloadsFromCluster(context.TODO(), userNamespace, c, nil)
+ if err != nil {
+ return nil, err
+ }
+ systemCaps, _, err := GetWorkloadsFromCluster(context.TODO(), types.DefaultKubeVelaNS, c, nil)
+ if err != nil {
+ return nil, err
+ }
+ caps = append(caps, systemCaps...)
+ return caps, nil
+ case types.TypeTrait:
+ caps, _, err := GetTraitsFromCluster(context.TODO(), userNamespace, c, nil)
+ if err != nil {
+ return nil, err
+ }
+ systemCaps, _, err := GetTraitsFromCluster(context.TODO(), types.DefaultKubeVelaNS, c, nil)
+ if err != nil {
+ return nil, err
+ }
+ caps = append(caps, systemCaps...)
+ return caps, nil
+ case types.TypeScope:
+
}
- return loadInstalledCapabilityWithType(dir, capT)
+
+ return nil, nil
}
// GetInstalledCapabilityWithCapName will get cap by alias
@@ -210,7 +234,7 @@ func LoadCapabilityFromSyncedCenter(dir string) ([]types.Capability, error) {
fmt.Printf("read file %s err %v\n", f.Name(), err)
continue
}
- tmp, err := ParseAndSyncCapability(data, filepath.Join(dir, ".tmp"))
+ tmp, err := ParseAndSyncCapability(data)
if err != nil {
fmt.Printf("get definition of %s err %v\n", f.Name(), err)
continue
diff --git a/references/plugins/references.go b/references/plugins/references.go
index bd24bc4d0..f350bcaac 100644
--- a/references/plugins/references.go
+++ b/references/plugins/references.go
@@ -183,7 +183,11 @@ func setDisplayFormat(format string) {
// GenerateReferenceDocs generates reference docs
func (ref *MarkdownReference) GenerateReferenceDocs(baseRefPath string) error {
- caps, err := LoadAllInstalledCapability()
+ c, err := common.InitBaseRestConfig()
+ if err != nil {
+ return err
+ }
+ caps, err := LoadAllInstalledCapability("default", c)
if err != nil {
return fmt.Errorf("failed to generate reference docs for all capabilities: %w", err)
}