Unverified Commit 97f45ae8 authored by Jianbo Sun's avatar Jianbo Sun Committed by GitHub
Browse files

code refactor (#935)

* code refactor

* update boilerplate.go.txt
parent 75ecf2f3
Showing with 161 additions and 146 deletions
+161 -146
// +build !ignore_autogenerated
/*
Copyright 2020 The KubeVela Authors.
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......
// +build !ignore_autogenerated
/*
Copyright 2020 The KubeVela Authors.
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......
......@@ -33,7 +33,7 @@ import (
oamcore "github.com/oam-dev/kubevela/apis/core.oam.dev"
velacore "github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/pkg/appfile/storage/driver"
"github.com/oam-dev/kubevela/pkg/appfile/driver"
velacontroller "github.com/oam-dev/kubevela/pkg/controller"
oamcontroller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
oamv1alpha2 "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2"
......
/*
Copyright 2020 The KubeVela Authors.
Copyright 2021 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
......
package appfile
package api
import (
"encoding/json"
......
package appfile
package api
import (
"os"
......
/*
Copyright 2020 The KubeVela Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package api
import (
"github.com/oam-dev/kubevela/pkg/appfile/template"
)
// Application is an implementation level object for Appfile, all vela commands will access AppFile from Appliction struct here.
type Application struct {
*AppFile `json:",inline"`
Tm template.Manager
}
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
}
package appfile
package api
import (
"encoding/json"
......
package appfile
package api
import (
"testing"
......
package application
package appfile
import (
"context"
"errors"
"fmt"
"reflect"
"sort"
......@@ -10,18 +11,45 @@ import (
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/appfile/storage"
"github.com/oam-dev/kubevela/pkg/appfile/storage/driver"
"github.com/oam-dev/kubevela/pkg/appfile/api"
"github.com/oam-dev/kubevela/pkg/appfile/template"
)
// NewEmptyApplication new empty application, only set tm
func NewEmptyApplication() (*driver.Application, error) {
func NewEmptyApplication() (*api.Application, error) {
tm, err := template.Load()
if err != nil {
return nil, err
}
return driver.NewApplication(nil, tm), nil
return NewApplication(nil, tm), nil
}
// NewApplication will create application object
func NewApplication(f *api.AppFile, tm template.Manager) *api.Application {
if f == nil {
f = api.NewAppFile()
}
return &api.Application{AppFile: f, Tm: tm}
}
// Validate will validate whether an Appfile is valid.
func Validate(app *api.Application) error {
if app.Name == "" {
return errors.New("name is required")
}
if len(app.Services) == 0 {
return errors.New("at least one service is required")
}
for name, svc := range app.Services {
for traitName, traitData := range svc.GetApplicationConfig() {
if app.Tm.IsTrait(traitName) {
if _, ok := traitData.(map[string]interface{}); !ok {
return fmt.Errorf("trait %s in '%s' must be map", traitName, name)
}
}
}
}
return nil
}
// IsNotFound is application not found error
......@@ -29,31 +57,31 @@ func IsNotFound(appName string, err error) bool {
return err != nil && err.Error() == fmt.Sprintf(`application "%s" not found`, appName)
}
// Load will load application with env and name from default vela home dir.
func Load(envName, appName string) (*driver.Application, error) {
app, err := storage.GetStorage().Get(envName, 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)
if err != nil {
return nil, err
}
err = app.Validate()
err = Validate(app)
return app, err
}
// Delete will delete an app along with it's appfile.
func Delete(envName, appName string) error {
return storage.GetStorage().Delete(envName, appName)
return GetStorage().Delete(envName, appName)
}
// List will list all apps
func List(envName string) ([]*driver.Application, error) {
respApps, err := storage.GetStorage().List(envName)
func List(envName string) ([]*api.Application, error) {
respApps, err := GetStorage().List(envName)
if err != nil {
return nil, err
}
var apps []*driver.Application
var apps []*api.Application
for _, resp := range respApps {
app := driver.NewApplication(resp.AppFile, resp.Tm)
err := app.Validate()
app := NewApplication(resp.AppFile, resp.Tm)
err := Validate(app)
if err != nil {
return nil, err
}
......@@ -63,7 +91,7 @@ func List(envName string) ([]*driver.Application, error) {
}
// MatchAppByComp will get application with componentName without AppName.
func MatchAppByComp(envName, compName string) (*driver.Application, error) {
func MatchAppByComp(envName, compName string) (*api.Application, error) {
apps, err := List(envName)
if err != nil {
return nil, err
......@@ -79,12 +107,12 @@ func MatchAppByComp(envName, compName string) (*driver.Application, error) {
}
// Save will save appfile into default dir.
func Save(app *driver.Application, envName string) error {
return storage.GetStorage().Save(app, envName)
func Save(app *api.Application, envName string) error {
return GetStorage().Save(app, envName)
}
// GetComponents will get oam components from Appfile.
func GetComponents(app *driver.Application) []string {
func GetComponents(app *api.Application) []string {
var components []string
for name := range app.Services {
components = append(components, name)
......@@ -94,7 +122,7 @@ func GetComponents(app *driver.Application) []string {
}
// GetServiceConfig will get service type and it's configuration
func GetServiceConfig(app *driver.Application, componentName string) (string, map[string]interface{}) {
func GetServiceConfig(app *api.Application, componentName string) (string, map[string]interface{}) {
svc, ok := app.Services[componentName]
if !ok {
return "", make(map[string]interface{})
......@@ -103,7 +131,7 @@ func GetServiceConfig(app *driver.Application, componentName string) (string, ma
}
// GetWorkload will get workload type and it's configuration
func GetWorkload(app *driver.Application, componentName string) (string, map[string]interface{}) {
func GetWorkload(app *api.Application, componentName string) (string, map[string]interface{}) {
svcType, config := GetServiceConfig(app, componentName)
if svcType == "" {
return "", make(map[string]interface{})
......@@ -119,7 +147,7 @@ func GetWorkload(app *driver.Application, componentName string) (string, map[str
}
// GetTraits will list all traits and it's configurations attached to the specified component.
func GetTraits(app *driver.Application, componentName string) (map[string]map[string]interface{}, error) {
func GetTraits(app *api.Application, componentName string) (map[string]map[string]interface{}, error) {
_, config := GetServiceConfig(app, componentName)
traitsData := make(map[string]map[string]interface{})
for k, v := range config {
......@@ -136,7 +164,7 @@ func GetTraits(app *driver.Application, componentName string) (map[string]map[st
}
// 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 *driver.Application, componentName, traitType string) (map[string]interface{}, error) {
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)
......@@ -149,7 +177,7 @@ func GetTraitsByType(app *driver.Application, componentName, traitType string) (
}
// GetAppConfig will get AppConfig from K8s cluster.
func GetAppConfig(ctx context.Context, c client.Client, app *driver.Application, env *types.EnvMeta) (*v1alpha2.ApplicationConfiguration, error) {
func GetAppConfig(ctx context.Context, c client.Client, app *api.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
......@@ -158,7 +186,7 @@ func GetAppConfig(ctx context.Context, c client.Client, app *driver.Application,
}
// GetApplication will get Application from K8s cluster.
func GetApplication(ctx context.Context, c client.Client, app *driver.Application, env *types.EnvMeta) (*v1alpha2.Application, error) {
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
......
package application
package appfile
import (
"errors"
......@@ -10,7 +10,6 @@ import (
"github.com/stretchr/testify/assert"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/appfile/storage/driver"
"github.com/oam-dev/kubevela/pkg/appfile/template"
)
......@@ -120,10 +119,10 @@ services:
Captype: types.TypeTrait,
}
}
app := driver.NewApplication(nil, tm)
app := NewApplication(nil, tm)
err := yaml.Unmarshal([]byte(c.raw), &app)
assert.NoError(t, err, caseName)
err = app.Validate()
err = Validate(app)
if c.InValid {
assert.Equal(t, c.InvalidReason, err)
continue
......@@ -145,7 +144,7 @@ func TestLoadNotExistsApplication(t *testing.T) {
now := time.Now().Unix()
appName := fmt.Sprintf("test-app-%d", now)
app, err := Load(types.DefaultEnvName, appName)
app, err := LoadApplication(types.DefaultEnvName, appName)
assert.Nil(t, app, caseName)
assert.Error(t, err, caseName)
......
......@@ -2,6 +2,8 @@ package driver
import (
"errors"
"github.com/oam-dev/kubevela/pkg/appfile/api"
)
// ConfigMapDriverName is local storage driver name
......@@ -9,7 +11,7 @@ const ConfigMapDriverName = "ConfigMap"
// ConfigMap Storage
type ConfigMap struct {
Driver
api.Driver
}
// NewConfigMapStorage get storage client of ConfigMap type
......@@ -23,13 +25,13 @@ func (c *ConfigMap) Name() string {
}
// List applications from configmap storage
func (c *ConfigMap) List(envName string) ([]*Application, error) {
func (c *ConfigMap) List(envName string) ([]*api.Application, error) {
// TODO support configmap storage
return nil, errors.New("not implement")
}
// Save applications from configmap storage
func (c *ConfigMap) Save(app *Application, envName string) error {
func (c *ConfigMap) Save(app *api.Application, envName string) error {
// TODO support configmap storage
return errors.New("not implement")
}
......@@ -41,7 +43,7 @@ func (c *ConfigMap) Delete(envName, appName string) error {
}
// Get applications from configmap storage
func (c *ConfigMap) Get(envName, appName string) (*Application, error) {
func (c *ConfigMap) Get(envName, appName string) (*api.Application, error) {
// TODO support configmap storage
return nil, errors.New("not implement")
}
......@@ -3,6 +3,8 @@ package driver
import (
"reflect"
"testing"
"github.com/oam-dev/kubevela/pkg/appfile/api"
)
func TestConfigMap_Delete(t *testing.T) {
......@@ -35,7 +37,7 @@ func TestConfigMap_Get(t *testing.T) {
tests := []struct {
name string
args args
want *Application
want *api.Application
wantErr bool
}{
// TODO: Add test cases.
......@@ -62,7 +64,7 @@ func TestConfigMap_List(t *testing.T) {
tests := []struct {
name string
args args
want []*Application
want []*api.Application
wantErr bool
}{
// TODO: Add test cases.
......@@ -101,7 +103,7 @@ func TestConfigMap_Name(t *testing.T) {
func TestConfigMap_Save(t *testing.T) {
type args struct {
app *Application
app *api.Application
envName string
}
tests := []struct {
......
......@@ -10,7 +10,7 @@ import (
"github.com/ghodss/yaml"
"github.com/oam-dev/kubevela/pkg/appfile"
"github.com/oam-dev/kubevela/pkg/appfile/api"
"github.com/oam-dev/kubevela/pkg/appfile/template"
"github.com/oam-dev/kubevela/pkg/utils/env"
"github.com/oam-dev/kubevela/pkg/utils/system"
......@@ -21,7 +21,7 @@ const LocalDriverName = "Local"
// Local Storage
type Local struct {
Driver
api.Driver
}
// NewLocalStorage get storage client of Local type
......@@ -35,7 +35,7 @@ func (l *Local) Name() string {
}
// List applications from local storage
func (l *Local) List(envName string) ([]*Application, error) {
func (l *Local) List(envName string) ([]*api.Application, error) {
appDir, err := getApplicationDir(envName)
if err != nil {
return nil, err
......@@ -44,7 +44,7 @@ func (l *Local) List(envName string) ([]*Application, error) {
if err != nil {
return nil, fmt.Errorf("list apps from %s err %w", appDir, err)
}
var apps []*Application
var apps []*api.Application
for _, f := range files {
if f.IsDir() {
continue
......@@ -62,7 +62,7 @@ func (l *Local) List(envName string) ([]*Application, error) {
}
// Save application from local storage
func (l *Local) Save(app *Application, envName string) error {
func (l *Local) Save(app *api.Application, envName string) error {
appDir, err := getApplicationDir(envName)
if err != nil {
return err
......@@ -89,7 +89,7 @@ func (l *Local) Delete(envName, appName string) error {
}
// Get application from local storage
func (l *Local) Get(envName, appName string) (*Application, error) {
func (l *Local) Get(envName, appName string) (*api.Application, error) {
appDir, err := getApplicationDir(envName)
if err != nil {
return nil, err
......@@ -116,7 +116,7 @@ func getApplicationDir(envName string) (string, error) {
}
// LoadFromFile will load application from file
func loadFromFile(fileName string) (*Application, error) {
func loadFromFile(fileName string) (*api.Application, error) {
tm, err := template.Load()
if err != nil {
return nil, err
......@@ -126,10 +126,10 @@ func loadFromFile(fileName string) (*Application, error) {
return nil, err
}
f, err := appfile.LoadFromFile(fileName)
f, err := api.LoadFromFile(fileName)
if err != nil {
return nil, err
}
app := &Application{AppFile: f, Tm: tm}
app := &api.Application{AppFile: f, Tm: tm}
return app, nil
}
......@@ -9,22 +9,22 @@ import (
"github.com/ghodss/yaml"
"github.com/oam-dev/kubevela/pkg/appfile"
"github.com/oam-dev/kubevela/pkg/appfile/api"
"github.com/oam-dev/kubevela/pkg/appfile/template"
)
var dir string
var tm template.Manager
var afile *appfile.AppFile
var afile *api.AppFile
var appName = "testsvc"
var envName = "default"
func init() {
dir, _ = getApplicationDir(envName)
tm, _ = template.Load()
afile = appfile.NewAppFile()
afile = api.NewAppFile()
afile.Name = appName
svcs := make(map[string]appfile.Service, 0)
svcs := make(map[string]api.Service, 0)
svcs["wordpress"] = map[string]interface{}{
"type": "webservice",
"image": "wordpress:php7.4-apache",
......@@ -45,10 +45,10 @@ func TestLocal_Get(t *testing.T) {
tests := []struct {
name string
args args
want *Application
want *api.Application
wantErr bool
}{
{"TestLocal_Get1", args{envName: envName, appName: appName}, &Application{AppFile: afile, Tm: tm}, false},
{"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) {
......@@ -90,7 +90,7 @@ func TestLocal_Delete(t *testing.T) {
func TestLocal_Save(t *testing.T) {
type args struct {
app *Application
app *api.Application
envName string
}
tests := []struct {
......@@ -98,7 +98,7 @@ func TestLocal_Save(t *testing.T) {
args args
wantErr bool
}{
{"TestLocal_Save1", args{&Application{AppFile: afile, Tm: nil}, envName}, false},
{"TestLocal_Save1", args{&api.Application{AppFile: afile, Tm: nil}, envName}, false},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
......@@ -114,12 +114,12 @@ func TestLocal_List(t *testing.T) {
type args struct {
envName string
}
want := make([]*Application, 0)
want = append(want, &Application{afile, tm})
want := make([]*api.Application, 0)
want = append(want, &api.Application{AppFile: afile, Tm: tm})
tests := []struct {
name string
args args
want []*Application
want []*api.Application
wantErr bool
}{
{"TestLocal_List1", args{envName}, want, false},
......@@ -205,10 +205,10 @@ func Test_loadFromFile(t *testing.T) {
tests := []struct {
name string
args args
want *Application
want *api.Application
wantErr bool
}{
{"testRespApp", args{fileName: filepath.Join(dir, appName+".yaml")}, &Application{AppFile: afile, Tm: tm}, false},
{"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) {
......
package application
package appfile
import (
"errors"
"github.com/oam-dev/kubevela/pkg/appfile"
"github.com/oam-dev/kubevela/pkg/appfile/storage/driver"
"github.com/oam-dev/kubevela/pkg/appfile/api"
)
// SetWorkload will set user workload for Appfile
func SetWorkload(app *driver.Application, componentName, workloadType string, workloadData map[string]interface{}) error {
func SetWorkload(app *api.Application, componentName, workloadType string, workloadData map[string]interface{}) error {
if app == nil {
return errors.New("app is nil pointer")
}
s, ok := app.Services[componentName]
if !ok {
s = appfile.Service{}
s = api.Service{}
}
s["type"] = workloadType
for k, v := range workloadData {
s[k] = v
}
app.Services[componentName] = s
return app.Validate()
return Validate(app)
}
// SetTrait will set user trait for Appfile
func SetTrait(app *driver.Application, componentName, traitType string, traitData map[string]interface{}) error {
func SetTrait(app *api.Application, componentName, traitType string, traitData map[string]interface{}) error {
if app == nil {
return errors.New("app is nil pointer")
}
......@@ -36,7 +35,7 @@ func SetTrait(app *driver.Application, componentName, traitType string, traitDat
s, ok := app.Services[componentName]
if !ok {
s = appfile.Service{}
s = api.Service{}
}
t, ok := s[traitType]
......@@ -49,11 +48,11 @@ func SetTrait(app *driver.Application, componentName, traitType string, traitDat
}
s[traitType] = t
app.Services[componentName] = s
return app.Validate()
return Validate(app)
}
// RemoveTrait will remove a trait from Appfile
func RemoveTrait(app *driver.Application, componentName, traitType string) error {
func RemoveTrait(app *api.Application, componentName, traitType string) error {
if app == nil {
return errors.New("app is nil pointer")
}
......@@ -67,7 +66,7 @@ func RemoveTrait(app *driver.Application, componentName, traitType string) error
}
// RemoveComponent will remove component from Appfile
func RemoveComponent(app *driver.Application, componentName string) error {
func RemoveComponent(app *api.Application, componentName string) error {
if app == nil {
return errors.New("app is nil pointer")
}
......
package application
package appfile
import (
"context"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
ctypes "k8s.io/apimachinery/pkg/types"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/appfile/storage/driver"
"github.com/oam-dev/kubevela/pkg/appfile/api"
cmdutil "github.com/oam-dev/kubevela/pkg/commands/util"
"github.com/oam-dev/kubevela/pkg/oam"
)
// BuildRun will build application and deploy from Appfile
func BuildRun(ctx context.Context, app *driver.Application, client client.Client, env *types.EnvMeta, io cmdutil.IOStreams) error {
func BuildRun(ctx context.Context, app *api.Application, client client.Client, env *types.EnvMeta, io cmdutil.IOStreams) error {
o, scopes, err := app.BuildOAMApplication(env, io, app.Tm, true)
if err != nil {
return err
......
package storage
package appfile
import (
"os"
"github.com/oam-dev/kubevela/pkg/appfile/storage/driver"
"github.com/oam-dev/kubevela/pkg/appfile/api"
"github.com/oam-dev/kubevela/pkg/appfile/driver"
"github.com/oam-dev/kubevela/pkg/utils/system"
)
......@@ -12,7 +13,7 @@ var store *Storage
// Storage is common storage client,use it to get app and others resource
type Storage struct {
driver.Driver
api.Driver
}
// GetStorage will create storage driver from the system environment of "STORAGE_DRIVER"
......@@ -33,12 +34,12 @@ func GetStorage() *Storage {
}
// List applications storage common implement
func (s *Storage) List(envName string) ([]*driver.Application, error) {
func (s *Storage) List(envName string) ([]*api.Application, error) {
return s.Driver.List(envName)
}
// Save application storage common implement
func (s *Storage) Save(app *driver.Application, envName string) error {
func (s *Storage) Save(app *api.Application, envName string) error {
return s.Driver.Save(app, envName)
}
......@@ -48,6 +49,6 @@ func (s *Storage) Delete(envName, appName string) error {
}
// Get application storage common implement
func (s *Storage) Get(envName, appName string) (*driver.Application, error) {
func (s *Storage) Get(envName, appName string) (*api.Application, error) {
return s.Driver.Get(envName, appName)
}
package driver
import (
"errors"
"fmt"
"github.com/oam-dev/kubevela/pkg/appfile"
"github.com/oam-dev/kubevela/pkg/appfile/template"
)
// Application is an implementation level object for Appfile, all vela commands will access AppFile from Appliction struct here.
type Application struct {
*appfile.AppFile `json:",inline"`
Tm template.Manager
}
// NewApplication will create application object
func NewApplication(f *appfile.AppFile, tm template.Manager) *Application {
if f == nil {
f = appfile.NewAppFile()
}
return &Application{AppFile: f, Tm: tm}
}
// Validate will validate whether an Appfile is valid.
func (app *Application) Validate() error {
if app.Name == "" {
return errors.New("name is required")
}
if len(app.Services) == 0 {
return errors.New("at least one service is required")
}
for name, svc := range app.Services {
for traitName, traitData := range svc.GetApplicationConfig() {
if app.Tm.IsTrait(traitName) {
if _, ok := traitData.(map[string]interface{}); !ok {
return fmt.Errorf("trait %s in '%s' must be map", traitName, name)
}
}
}
}
return nil
}
// 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
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment