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

make CUE inner kube package as a standalone package && clean code (#1263)

parent 30f30d9c
Showing with 324 additions and 152 deletions
+324 -152
...@@ -314,15 +314,13 @@ func TestPackage(t *testing.T) { ...@@ -314,15 +314,13 @@ func TestPackage(t *testing.T) {
} }
} }
` `
mypd := &PackageDiscover{pkgKinds: make(map[string][]string)}
pkg := newPackage("oss") mypd.addKubeCUEPackagesFromCluster(openAPISchema)
assert.NilError(t, pkg.addOpenAPI(openAPISchema))
pkg.mount()
bi := build.NewContext().NewInstance("", nil) bi := build.NewContext().NewInstance("", nil)
AddVelaInternalPackagesFor(bi) mypd.ImportBuiltinPackagesFor(bi)
bi.AddFile("-", ` bi.AddFile("-", `
import "oss" import "kube/test.io/v1"
output: oss.#Bucket output: v1.#Bucket
`) `)
var r cue.Runtime var r cue.Runtime
inst, err := r.Build(bi) inst, err := r.Build(bi)
...@@ -430,13 +428,13 @@ func TestProcessFile(t *testing.T) { ...@@ -430,13 +428,13 @@ func TestProcessFile(t *testing.T) {
} }
func TestMount(t *testing.T) { func TestMount(t *testing.T) {
velaBuiltinPkgs = nil mypd := &PackageDiscover{pkgKinds: make(map[string][]string)}
testPkg := newPackage("foo") testPkg := newPackage("foo")
testPkg.mount() mypd.mount(testPkg, []string{"abc"})
assert.Equal(t, len(velaBuiltinPkgs), 1) assert.Equal(t, len(mypd.velaBuiltinPackages), 1)
testPkg.mount() mypd.mount(testPkg, []string{"abc"})
assert.Equal(t, len(velaBuiltinPkgs), 1) assert.Equal(t, len(mypd.velaBuiltinPackages), 1)
assert.Equal(t, velaBuiltinPkgs[0], testPkg.Instance) assert.Equal(t, mypd.velaBuiltinPackages[0], testPkg.Instance)
} }
func TestGetGVK(t *testing.T) { func TestGetGVK(t *testing.T) {
......
...@@ -39,6 +39,7 @@ var cfg *rest.Config ...@@ -39,6 +39,7 @@ var cfg *rest.Config
var k8sClient client.Client var k8sClient client.Client
var testEnv *envtest.Environment var testEnv *envtest.Environment
var scheme = runtime.NewScheme() var scheme = runtime.NewScheme()
var pd *PackageDiscover
func TestDefinition(t *testing.T) { func TestDefinition(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)
...@@ -64,6 +65,8 @@ var _ = BeforeSuite(func(done Done) { ...@@ -64,6 +65,8 @@ var _ = BeforeSuite(func(done Done) {
k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) k8sClient, err = client.New(cfg, client.Options{Scheme: scheme})
Expect(err).ToNot(HaveOccurred()) Expect(err).ToNot(HaveOccurred())
Expect(k8sClient).ToNot(BeNil()) Expect(k8sClient).ToNot(BeNil())
pd, err = NewPackageDiscover(cfg)
Expect(err).ToNot(HaveOccurred())
close(done) close(done)
}, 60) }, 60)
......
...@@ -39,15 +39,14 @@ const ( ...@@ -39,15 +39,14 @@ const (
// AbstractEngine defines Definition's Render interface // AbstractEngine defines Definition's Render interface
type AbstractEngine interface { type AbstractEngine interface {
Params(params interface{}) AbstractEngine Complete(ctx process.Context, abstractTemplate string, params interface{}) error
Complete(ctx process.Context, abstractTemplate string) error
HealthCheck(ctx process.Context, cli client.Client, ns string, healthPolicyTemplate string) (bool, error) HealthCheck(ctx process.Context, cli client.Client, ns string, healthPolicyTemplate string) (bool, error)
Status(ctx process.Context, cli client.Client, ns string, customStatusTemplate string) (string, error) Status(ctx process.Context, cli client.Client, ns string, customStatusTemplate string) (string, error)
} }
type def struct { type def struct {
name string name string
params interface{} pd *PackageDiscover
} }
type workloadDef struct { type workloadDef struct {
...@@ -55,29 +54,23 @@ type workloadDef struct { ...@@ -55,29 +54,23 @@ type workloadDef struct {
} }
// NewWorkloadAbstractEngine create Workload Definition AbstractEngine // NewWorkloadAbstractEngine create Workload Definition AbstractEngine
func NewWorkloadAbstractEngine(name string) AbstractEngine { func NewWorkloadAbstractEngine(name string, pd *PackageDiscover) AbstractEngine {
return &workloadDef{ return &workloadDef{
def: def{ def: def{
name: name, name: name,
params: nil, pd: pd,
}, },
} }
} }
// Params set definition's params
func (wd *workloadDef) Params(params interface{}) AbstractEngine {
wd.params = params
return wd
}
// Complete do workload definition's rendering // Complete do workload definition's rendering
func (wd *workloadDef) Complete(ctx process.Context, abstractTemplate string) error { func (wd *workloadDef) Complete(ctx process.Context, abstractTemplate string, params interface{}) error {
bi := build.NewContext().NewInstance("", nil) bi := build.NewContext().NewInstance("", nil)
if err := bi.AddFile("-", abstractTemplate); err != nil { if err := bi.AddFile("-", abstractTemplate); err != nil {
return errors.WithMessagef(err, "invalid cue template of workload %s", wd.name) return errors.WithMessagef(err, "invalid cue template of workload %s", wd.name)
} }
if wd.params != nil { if params != nil {
bt, err := json.Marshal(wd.params) bt, err := json.Marshal(params)
if err != nil { if err != nil {
return errors.WithMessagef(err, "marshal parameter of workload %s", wd.name) return errors.WithMessagef(err, "marshal parameter of workload %s", wd.name)
} }
...@@ -89,40 +82,42 @@ func (wd *workloadDef) Complete(ctx process.Context, abstractTemplate string) er ...@@ -89,40 +82,42 @@ func (wd *workloadDef) Complete(ctx process.Context, abstractTemplate string) er
if err := bi.AddFile("-", ctx.BaseContextFile()); err != nil { if err := bi.AddFile("-", ctx.BaseContextFile()); err != nil {
return err return err
} }
AddVelaInternalPackagesFor(bi) wd.pd.ImportBuiltinPackagesFor(bi)
var r cue.Runtime
inst, err := r.Build(bi)
if err != nil {
return err
}
instances := cue.Build([]*build.Instance{bi}) if err := inst.Value().Err(); err != nil {
for _, inst := range instances { return errors.WithMessagef(err, "invalid cue template of workload %s after merge parameter and context", wd.name)
if err := inst.Value().Err(); err != nil { }
return errors.WithMessagef(err, "invalid cue template of workload %s after merge parameter and context", wd.name) output := inst.Lookup(OutputFieldName)
} base, err := model.NewBase(output)
output := inst.Lookup(OutputFieldName) if err != nil {
base, err := model.NewBase(output) return errors.WithMessagef(err, "invalid output of workload %s", wd.name)
if err != nil { }
return errors.WithMessagef(err, "invalid output of workload %s", wd.name) ctx.SetBase(base)
}
ctx.SetBase(base)
// we will support outputs for workload composition, and it will become trait in AppConfig. // we will support outputs for workload composition, and it will become trait in AppConfig.
outputs := inst.Lookup(OutputsFieldName) outputs := inst.Lookup(OutputsFieldName)
if !outputs.Exists() { if !outputs.Exists() {
return nil
}
st, err := outputs.Struct()
if err != nil {
return errors.WithMessagef(err, "invalid outputs of workload %s", wd.name)
}
for i := 0; i < st.Len(); i++ {
fieldInfo := st.Field(i)
if fieldInfo.IsDefinition || fieldInfo.IsHidden || fieldInfo.IsOptional {
continue continue
} }
st, err := outputs.Struct() other, err := model.NewOther(fieldInfo.Value)
if err != nil { if err != nil {
return errors.WithMessagef(err, "invalid outputs of workload %s", wd.name) return errors.WithMessagef(err, "invalid outputs(%s) of workload %s", fieldInfo.Name, wd.name)
}
for i := 0; i < st.Len(); i++ {
fieldInfo := st.Field(i)
if fieldInfo.IsDefinition || fieldInfo.IsHidden || fieldInfo.IsOptional {
continue
}
other, err := model.NewOther(fieldInfo.Value)
if err != nil {
return errors.WithMessagef(err, "invalid outputs(%s) of workload %s", fieldInfo.Name, wd.name)
}
ctx.AppendAuxiliaries(process.Auxiliary{Ins: other, Type: AuxiliaryWorkload, Name: fieldInfo.Name})
} }
ctx.AppendAuxiliaries(process.Auxiliary{Ins: other, Type: AuxiliaryWorkload, Name: fieldInfo.Name})
} }
return nil return nil
} }
...@@ -238,28 +233,23 @@ type traitDef struct { ...@@ -238,28 +233,23 @@ type traitDef struct {
} }
// NewTraitAbstractEngine create Trait Definition AbstractEngine // NewTraitAbstractEngine create Trait Definition AbstractEngine
func NewTraitAbstractEngine(name string) AbstractEngine { func NewTraitAbstractEngine(name string, pd *PackageDiscover) AbstractEngine {
return &traitDef{ return &traitDef{
def: def{ def: def{
name: name, name: name,
pd: pd,
}, },
} }
} }
// Params set definition's params
func (td *traitDef) Params(params interface{}) AbstractEngine {
td.params = params
return td
}
// Complete do trait definition's rendering // Complete do trait definition's rendering
func (td *traitDef) Complete(ctx process.Context, abstractTemplate string) error { func (td *traitDef) Complete(ctx process.Context, abstractTemplate string, params interface{}) error {
bi := build.NewContext().NewInstance("", nil) bi := build.NewContext().NewInstance("", nil)
if err := bi.AddFile("-", abstractTemplate); err != nil { if err := bi.AddFile("-", abstractTemplate); err != nil {
return errors.WithMessagef(err, "invalid template of trait %s", td.name) return errors.WithMessagef(err, "invalid template of trait %s", td.name)
} }
if td.params != nil { if params != nil {
bt, err := json.Marshal(td.params) bt, err := json.Marshal(params)
if err != nil { if err != nil {
return errors.WithMessagef(err, "marshal parameter of trait %s", td.name) return errors.WithMessagef(err, "marshal parameter of trait %s", td.name)
} }
...@@ -271,7 +261,7 @@ func (td *traitDef) Complete(ctx process.Context, abstractTemplate string) error ...@@ -271,7 +261,7 @@ func (td *traitDef) Complete(ctx process.Context, abstractTemplate string) error
if err := bi.AddFile("context", ctx.BaseContextFile()); err != nil { if err := bi.AddFile("context", ctx.BaseContextFile()); err != nil {
return errors.WithMessagef(err, "invalid context of trait %s", td.name) return errors.WithMessagef(err, "invalid context of trait %s", td.name)
} }
AddVelaInternalPackagesFor(bi) td.pd.ImportBuiltinPackagesFor(bi)
instances := cue.Build([]*build.Instance{bi}) instances := cue.Build([]*build.Instance{bi})
for _, inst := range instances { for _, inst := range instances {
......
...@@ -107,8 +107,8 @@ parameter: { ...@@ -107,8 +107,8 @@ parameter: {
for _, v := range testCases { for _, v := range testCases {
ctx := process.NewContext("test", "myapp", "myapp-v1") ctx := process.NewContext("test", "myapp", "myapp-v1")
wt := NewWorkloadAbstractEngine("testworkload") wt := NewWorkloadAbstractEngine("testworkload", &PackageDiscover{})
assert.NoError(t, wt.Params(v.params).Complete(ctx, v.workloadTemplate)) assert.NoError(t, wt.Complete(ctx, v.workloadTemplate, v.params))
base, assists := ctx.Output() base, assists := ctx.Output()
assert.Equal(t, len(v.expAssObjs), len(assists)) assert.Equal(t, len(v.expAssObjs), len(assists))
assert.NotNil(t, base) assert.NotNil(t, base)
...@@ -432,6 +432,70 @@ parameter: { ...@@ -432,6 +432,70 @@ parameter: {
"t3ingress": &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "networking.k8s.io/v1beta1", "kind": "Ingress", "labels": map[string]interface{}{"config": "enemies-data"}, "metadata": map[string]interface{}{"name": "test"}, "spec": map[string]interface{}{"rules": []interface{}{map[string]interface{}{"host": "example.com", "http": map[string]interface{}{"paths": []interface{}{map[string]interface{}{"backend": map[string]interface{}{"serviceName": "test", "servicePort": int64(1080)}, "path": "ping"}}}}}}}}, "t3ingress": &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "networking.k8s.io/v1beta1", "kind": "Ingress", "labels": map[string]interface{}{"config": "enemies-data"}, "metadata": map[string]interface{}{"name": "test"}, "spec": map[string]interface{}{"rules": []interface{}{map[string]interface{}{"host": "example.com", "http": map[string]interface{}{"paths": []interface{}{map[string]interface{}{"backend": map[string]interface{}{"serviceName": "test", "servicePort": int64(1080)}, "path": "ping"}}}}}}}},
}, },
}, },
"outputs trait with schema": {
traitTemplate: `
#Service:{
apiVersion: string
kind: string
}
#Ingress:{
apiVersion: string
kind: string
}
outputs:{
service: #Service
ingress: #Ingress
}
outputs: service: {
apiVersion: "v1"
kind: "Service"
}
outputs: ingress: {
apiVersion: "extensions/v1beta1"
kind: "Ingress"
}
parameter: {
type: string
host: string
}`,
params: map[string]interface{}{
"type": "ClusterIP",
"host": "example.com",
},
expWorkload: &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"spec": map[string]interface{}{
"replicas": int64(2),
"selector": map[string]interface{}{
"matchLabels": map[string]interface{}{
"app.oam.dev/component": "test"}},
"template": map[string]interface{}{
"metadata": map[string]interface{}{
"labels": map[string]interface{}{"app.oam.dev/component": "test"},
},
"spec": map[string]interface{}{
"containers": []interface{}{map[string]interface{}{
"envFrom": []interface{}{map[string]interface{}{
"configMapRef": map[string]interface{}{"name": "testgame-config"},
}},
"image": "website:0.1",
"name": "main",
"ports": []interface{}{map[string]interface{}{"containerPort": int64(443)}}}}}}}},
},
traitName: "t2",
expAssObjs: map[string]runtime.Object{
"AuxiliaryWorkloadgameconfig": &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "v1",
"kind": "ConfigMap",
"metadata": map[string]interface{}{"name": "testgame-config"}, "data": map[string]interface{}{"enemies": "enemies-data", "lives": "lives-data"}},
},
"t2service": &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "v1", "kind": "Service"}},
"t2ingress": &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "extensions/v1beta1", "kind": "Ingress"}},
},
},
} }
for cassinfo, v := range tds { for cassinfo, v := range tds {
...@@ -491,18 +555,18 @@ parameter: { ...@@ -491,18 +555,18 @@ parameter: {
` `
ctx := process.NewContext("test", "myapp", "myapp-v1") ctx := process.NewContext("test", "myapp", "myapp-v1")
wt := NewWorkloadAbstractEngine("-") wt := NewWorkloadAbstractEngine("-", &PackageDiscover{})
if err := wt.Params(map[string]interface{}{ if err := wt.Complete(ctx, baseTemplate, map[string]interface{}{
"replicas": 2, "replicas": 2,
"enemies": "enemies-data", "enemies": "enemies-data",
"lives": "lives-data", "lives": "lives-data",
"port": 443, "port": 443,
}).Complete(ctx, baseTemplate); err != nil { }); err != nil {
t.Error(err) t.Error(err)
return return
} }
td := NewTraitAbstractEngine(v.traitName) td := NewTraitAbstractEngine(v.traitName, &PackageDiscover{})
assert.NoError(t, td.Params(v.params).Complete(ctx, v.traitTemplate)) assert.NoError(t, td.Complete(ctx, v.traitTemplate, v.params))
base, assists := ctx.Output() base, assists := ctx.Output()
assert.Equal(t, len(v.expAssObjs), len(assists), cassinfo) assert.Equal(t, len(v.expAssObjs), len(assists), cassinfo)
assert.NotNil(t, base) assert.NotNil(t, base)
......
package model package model
import ( import (
"strings"
"github.com/pkg/errors"
"cuelang.org/go/cue/build"
"cuelang.org/go/cue" "cuelang.org/go/cue"
"cuelang.org/go/cue/ast" "cuelang.org/go/cue/ast"
"cuelang.org/go/cue/format" "cuelang.org/go/cue/format"
...@@ -34,28 +40,31 @@ func (inst *instance) IsBase() bool { ...@@ -34,28 +40,31 @@ func (inst *instance) IsBase() bool {
} }
func (inst *instance) Compile() ([]byte, error) { func (inst *instance) Compile() ([]byte, error) {
bi := build.NewContext().NewInstance("", nil)
err := bi.AddFile("-", inst.v)
if err != nil {
return nil, err
}
var r cue.Runtime var r cue.Runtime
cueInst, err := r.Compile("-", inst.v) it, err := r.Build(bi)
if err != nil { if err != nil {
return nil, err return nil, err
} }
// compiled object should be final and concrete value // compiled object should be final and concrete value
if err := cueInst.Value().Validate(cue.Concrete(true), cue.Final()); err != nil { if err := it.Value().Validate(cue.Concrete(true), cue.Final()); err != nil {
return nil, err return nil, it.Err
} }
return cueInst.Value().MarshalJSON() return it.Value().MarshalJSON()
} }
// Unstructured convert cue values to unstructured.Unstructured // Unstructured convert cue values to unstructured.Unstructured
// TODO(wonderflow): will it be better if we try to decode it to concrete object(such as K8s Deployment) by using runtime.Schema?ß // TODO(wonderflow): will it be better if we try to decode it to concrete object(such as K8s Deployment) by using runtime.Schema?
func (inst *instance) Unstructured() (*unstructured.Unstructured, error) { func (inst *instance) Unstructured() (*unstructured.Unstructured, error) {
jsonv, err := inst.Compile() jsonv, err := inst.Compile()
if err != nil { if err != nil {
return nil, err return nil, err
} }
o := &unstructured.Unstructured{} o := &unstructured.Unstructured{}
if err := o.UnmarshalJSON(jsonv); err != nil { if err := o.UnmarshalJSON(jsonv); err != nil {
return nil, err return nil, err
} }
...@@ -107,7 +116,13 @@ func openPrint(v cue.Value) (string, error) { ...@@ -107,7 +116,13 @@ func openPrint(v cue.Value) (string, error) {
} }
ret, err := format.Node(f) ret, err := format.Node(f)
return string(ret), err if err != nil {
return "", err
}
if strings.Contains(string(ret), "_|_") {
return "", errors.New(string(ret))
}
return string(ret), nil
} }
func listOpen(expr ast.Node) { func listOpen(expr ast.Node) {
......
...@@ -122,5 +122,39 @@ output: { ...@@ -122,5 +122,39 @@ output: {
assert.Error(t, err) assert.Error(t, err)
var expnil *unstructured.Unstructured var expnil *unstructured.Unstructured
assert.Equal(t, expnil, data) assert.Equal(t, expnil, data)
}
func TestError(t *testing.T) {
ins := &instance{
v: ``,
}
_, err := ins.Unstructured()
assert.Equal(t, err.Error(), "Object 'Kind' is missing in '{}'")
ins = &instance{
v: `
apiVersion: "apps/v1"
kind: "Deployment"
metadata: name: parameter.name
`,
}
_, err = ins.Unstructured()
assert.Equal(t, err.Error(), `metadata.name: reference "parameter" not found`)
ins = &instance{
v: `
apiVersion: "apps/v1"
kind: "Deployment"
metadata: name: "abc"
`,
}
obj, err := ins.Unstructured()
assert.Equal(t, err, nil)
assert.Equal(t, obj, &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "apps/v1",
"kind": "Deployment",
"metadata": map[string]interface{}{
"name": "abc",
},
},
})
} }
...@@ -4,10 +4,9 @@ import ( ...@@ -4,10 +4,9 @@ import (
"context" "context"
"testing" "testing"
"github.com/stretchr/testify/assert"
"cuelang.org/go/cue" "cuelang.org/go/cue"
"github.com/crossplane/crossplane-runtime/pkg/test" "github.com/crossplane/crossplane-runtime/pkg/test"
"github.com/stretchr/testify/assert"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
ktypes "k8s.io/apimachinery/pkg/types" ktypes "k8s.io/apimachinery/pkg/types"
......
package types package common
import ( import (
"fmt"
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"k8s.io/client-go/rest" "k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/client/config" "sigs.k8s.io/controller-runtime/pkg/client/config"
"github.com/oam-dev/kubevela/pkg/dsl/definition"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
) )
// Args is args for controller-runtime client // Args is args for controller-runtime client
...@@ -12,6 +17,8 @@ type Args struct { ...@@ -12,6 +17,8 @@ type Args struct {
Config *rest.Config Config *rest.Config
Schema *runtime.Scheme Schema *runtime.Scheme
Client client.Client Client client.Client
dm discoverymapper.DiscoveryMapper
pd *definition.PackageDiscover
} }
// SetConfig insert kubeconfig into Args // SetConfig insert kubeconfig into Args
...@@ -41,3 +48,39 @@ func (a *Args) GetClient() (client.Client, error) { ...@@ -41,3 +48,39 @@ func (a *Args) GetClient() (client.Client, error) {
a.Client = newClient a.Client = newClient
return a.Client, nil return a.Client, nil
} }
// GetDiscoveryMapper get discoveryMapper client if exist, create if not exist.
func (a *Args) GetDiscoveryMapper() (discoverymapper.DiscoveryMapper, error) {
if a.Config == nil {
if err := a.SetConfig(); err != nil {
return nil, err
}
}
if a.dm != nil {
return a.dm, nil
}
dm, err := discoverymapper.New(a.Config)
if err != nil {
return nil, fmt.Errorf("failed to create CRD discovery client %w", err)
}
a.dm = dm
return dm, nil
}
// GetPackageDiscover get PackageDiscover client if exist, create if not exist.
func (a *Args) GetPackageDiscover() (*definition.PackageDiscover, error) {
if a.Config == nil {
if err := a.SetConfig(); err != nil {
return nil, err
}
}
if a.pd != nil {
return a.pd, nil
}
pd, err := definition.NewPackageDiscover(a.Config)
if err != nil {
return nil, fmt.Errorf("failed to create CRD discovery for CUE package client %w", err)
}
a.pd = pd
return pd, nil
}
...@@ -24,7 +24,6 @@ import ( ...@@ -24,7 +24,6 @@ import (
core "github.com/oam-dev/kubevela/apis/core.oam.dev" core "github.com/oam-dev/kubevela/apis/core.oam.dev"
"github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1" "github.com/oam-dev/kubevela/apis/standard.oam.dev/v1alpha1"
"github.com/oam-dev/kubevela/apis/types"
mycue "github.com/oam-dev/kubevela/pkg/cue" mycue "github.com/oam-dev/kubevela/pkg/cue"
) )
...@@ -42,14 +41,14 @@ func init() { ...@@ -42,14 +41,14 @@ func init() {
} }
// InitBaseRestConfig will return reset config for create controller runtime client // InitBaseRestConfig will return reset config for create controller runtime client
func InitBaseRestConfig() (types.Args, error) { func InitBaseRestConfig() (Args, error) {
restConf, err := config.GetConfig() restConf, err := config.GetConfig()
if err != nil { if err != nil {
fmt.Println("get kubeConfig err", err) fmt.Println("get kubeConfig err", err)
os.Exit(1) os.Exit(1)
} }
return types.Args{ return Args{
Config: restConf, Config: restConf,
Schema: Scheme, Schema: Scheme,
}, nil }, nil
......
...@@ -3,6 +3,7 @@ package core_oam_dev ...@@ -3,6 +3,7 @@ package core_oam_dev
import ( import (
"sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/manager"
controller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
"github.com/oam-dev/kubevela/pkg/webhook/core.oam.dev/v1alpha2/application" "github.com/oam-dev/kubevela/pkg/webhook/core.oam.dev/v1alpha2/application"
"github.com/oam-dev/kubevela/pkg/webhook/core.oam.dev/v1alpha2/applicationconfiguration" "github.com/oam-dev/kubevela/pkg/webhook/core.oam.dev/v1alpha2/applicationconfiguration"
"github.com/oam-dev/kubevela/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment" "github.com/oam-dev/kubevela/pkg/webhook/core.oam.dev/v1alpha2/applicationdeployment"
...@@ -11,22 +12,13 @@ import ( ...@@ -11,22 +12,13 @@ import (
) )
// Register will be called in main and register all validation handlers // Register will be called in main and register all validation handlers
func Register(mgr manager.Manager) error { func Register(mgr manager.Manager, args controller.Args) {
if err := application.RegisterValidatingHandler(mgr); err != nil { application.RegisterValidatingHandler(mgr, args)
return err applicationconfiguration.RegisterValidatingHandler(mgr, args)
} traitdefinition.RegisterValidatingHandler(mgr, args)
if err := applicationconfiguration.RegisterValidatingHandler(mgr); err != nil {
return err
}
if err := traitdefinition.RegisterValidatingHandler(mgr); err != nil {
return err
}
applicationconfiguration.RegisterMutatingHandler(mgr) applicationconfiguration.RegisterMutatingHandler(mgr)
applicationdeployment.RegisterMutatingHandler(mgr) applicationdeployment.RegisterMutatingHandler(mgr)
applicationdeployment.RegisterValidatingHandler(mgr) applicationdeployment.RegisterValidatingHandler(mgr)
if err := component.RegisterMutatingHandler(mgr); err != nil { component.RegisterMutatingHandler(mgr, args)
return err
}
component.RegisterValidatingHandler(mgr) component.RegisterValidatingHandler(mgr)
return nil
} }
...@@ -4,6 +4,8 @@ import ( ...@@ -4,6 +4,8 @@ import (
"context" "context"
"net/http" "net/http"
"github.com/oam-dev/kubevela/pkg/dsl/definition"
admissionv1beta1 "k8s.io/api/admission/v1beta1" admissionv1beta1 "k8s.io/api/admission/v1beta1"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/manager" "sigs.k8s.io/controller-runtime/pkg/manager"
...@@ -12,6 +14,7 @@ import ( ...@@ -12,6 +14,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
controller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
"github.com/oam-dev/kubevela/pkg/oam/util" "github.com/oam-dev/kubevela/pkg/oam/util"
) )
...@@ -21,6 +24,7 @@ var _ admission.Handler = &ValidatingHandler{} ...@@ -21,6 +24,7 @@ var _ admission.Handler = &ValidatingHandler{}
// ValidatingHandler handles application // ValidatingHandler handles application
type ValidatingHandler struct { type ValidatingHandler struct {
dm discoverymapper.DiscoveryMapper dm discoverymapper.DiscoveryMapper
pd *definition.PackageDiscover
Client client.Client Client client.Client
// Decoder decodes objects // Decoder decodes objects
Decoder *admission.Decoder Decoder *admission.Decoder
...@@ -75,13 +79,8 @@ func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) a ...@@ -75,13 +79,8 @@ func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) a
return admission.ValidationResponse(true, "") return admission.ValidationResponse(true, "")
} }
// RegisterValidatingHandler will regsiter application validate handler to the webhook // RegisterValidatingHandler will register application validate handler to the webhook
func RegisterValidatingHandler(mgr manager.Manager) error { func RegisterValidatingHandler(mgr manager.Manager, args controller.Args) {
mapper, err := discoverymapper.New(mgr.GetConfig())
if err != nil {
return err
}
server := mgr.GetWebhookServer() server := mgr.GetWebhookServer()
server.Register("/validating-core-oam-dev-v1alpha2-applications", &webhook.Admission{Handler: &ValidatingHandler{dm: mapper}}) server.Register("/validating-core-oam-dev-v1alpha2-applications", &webhook.Admission{Handler: &ValidatingHandler{dm: args.DiscoveryMapper, pd: args.PackageDiscover}})
return nil
} }
...@@ -13,7 +13,7 @@ import ( ...@@ -13,7 +13,7 @@ import (
func (h *ValidatingHandler) ValidateCreate(ctx context.Context, app *v1alpha2.Application) field.ErrorList { func (h *ValidatingHandler) ValidateCreate(ctx context.Context, app *v1alpha2.Application) field.ErrorList {
var componentErrs field.ErrorList var componentErrs field.ErrorList
// try to generate an app file // try to generate an app file
appParser := appfile.NewApplicationParser(h.Client, h.dm) appParser := appfile.NewApplicationParser(h.Client, h.dm, h.pd)
if _, err := appParser.GenerateAppFile(ctx, app.Name, app); err != nil { if _, err := appParser.GenerateAppFile(ctx, app.Name, app); err != nil {
componentErrs = append(componentErrs, field.Invalid(field.NewPath("spec"), app, err.Error())) componentErrs = append(componentErrs, field.Invalid(field.NewPath("spec"), app, err.Error()))
} }
......
...@@ -19,6 +19,7 @@ import ( ...@@ -19,6 +19,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
controller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
"github.com/oam-dev/kubevela/pkg/oam/util" "github.com/oam-dev/kubevela/pkg/oam/util"
) )
...@@ -313,14 +314,10 @@ func (h *ValidatingHandler) InjectDecoder(d *admission.Decoder) error { ...@@ -313,14 +314,10 @@ func (h *ValidatingHandler) InjectDecoder(d *admission.Decoder) error {
} }
// RegisterValidatingHandler will register application configuration validation to webhook // RegisterValidatingHandler will register application configuration validation to webhook
func RegisterValidatingHandler(mgr manager.Manager) error { func RegisterValidatingHandler(mgr manager.Manager, args controller.Args) {
server := mgr.GetWebhookServer() server := mgr.GetWebhookServer()
mapper, err := discoverymapper.New(mgr.GetConfig())
if err != nil {
return err
}
server.Register("/validating-core-oam-dev-v1alpha2-applicationconfigurations", &webhook.Admission{Handler: &ValidatingHandler{ server.Register("/validating-core-oam-dev-v1alpha2-applicationconfigurations", &webhook.Admission{Handler: &ValidatingHandler{
Mapper: mapper, Mapper: args.DiscoveryMapper,
Validators: []AppConfigValidator{ Validators: []AppConfigValidator{
AppConfigValidateFunc(ValidateRevisionNameFn), AppConfigValidateFunc(ValidateRevisionNameFn),
AppConfigValidateFunc(ValidateWorkloadNameForVersioningFn), AppConfigValidateFunc(ValidateWorkloadNameForVersioningFn),
...@@ -329,5 +326,4 @@ func RegisterValidatingHandler(mgr manager.Manager) error { ...@@ -329,5 +326,4 @@ func RegisterValidatingHandler(mgr manager.Manager) error {
// TODO(wonderflow): Add more validation logic here. // TODO(wonderflow): Add more validation logic here.
}, },
}}) }})
return nil
} }
...@@ -22,8 +22,6 @@ import ( ...@@ -22,8 +22,6 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/types"
...@@ -35,8 +33,9 @@ import ( ...@@ -35,8 +33,9 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
controller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
"github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
"github.com/oam-dev/kubevela/pkg/oam/util" "github.com/oam-dev/kubevela/pkg/oam/util"
) )
...@@ -154,12 +153,7 @@ func (h *MutatingHandler) InjectDecoder(d *admission.Decoder) error { ...@@ -154,12 +153,7 @@ func (h *MutatingHandler) InjectDecoder(d *admission.Decoder) error {
} }
// RegisterMutatingHandler will register component mutation handler to the webhook // RegisterMutatingHandler will register component mutation handler to the webhook
func RegisterMutatingHandler(mgr manager.Manager) error { func RegisterMutatingHandler(mgr manager.Manager, args controller.Args) {
mapper, err := discoverymapper.New(mgr.GetConfig())
if err != nil {
return err
}
server := mgr.GetWebhookServer() server := mgr.GetWebhookServer()
server.Register("/mutating-core-oam-dev-v1alpha2-components", &webhook.Admission{Handler: &MutatingHandler{Mapper: mapper}}) server.Register("/mutating-core-oam-dev-v1alpha2-components", &webhook.Admission{Handler: &MutatingHandler{Mapper: args.DiscoveryMapper}})
return nil
} }
...@@ -5,8 +5,7 @@ import ( ...@@ -5,8 +5,7 @@ import (
"fmt" "fmt"
"net/http" "net/http"
"github.com/oam-dev/kubevela/pkg/oam/util" "github.com/pkg/errors"
admissionv1beta1 "k8s.io/api/admission/v1beta1" admissionv1beta1 "k8s.io/api/admission/v1beta1"
"k8s.io/klog" "k8s.io/klog"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
...@@ -15,10 +14,10 @@ import ( ...@@ -15,10 +14,10 @@ import (
"sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission" "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
"github.com/pkg/errors"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
controller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
"github.com/oam-dev/kubevela/pkg/oam/util"
) )
const ( const (
...@@ -96,20 +95,15 @@ func (h *ValidatingHandler) InjectDecoder(d *admission.Decoder) error { ...@@ -96,20 +95,15 @@ func (h *ValidatingHandler) InjectDecoder(d *admission.Decoder) error {
} }
// RegisterValidatingHandler will register TraitDefinition validation to webhook // RegisterValidatingHandler will register TraitDefinition validation to webhook
func RegisterValidatingHandler(mgr manager.Manager) error { func RegisterValidatingHandler(mgr manager.Manager, args controller.Args) {
server := mgr.GetWebhookServer() server := mgr.GetWebhookServer()
mapper, err := discoverymapper.New(mgr.GetConfig())
if err != nil {
return err
}
server.Register("/validating-core-oam-dev-v1alpha2-traitdefinitions", &webhook.Admission{Handler: &ValidatingHandler{ server.Register("/validating-core-oam-dev-v1alpha2-traitdefinitions", &webhook.Admission{Handler: &ValidatingHandler{
Mapper: mapper, Mapper: args.DiscoveryMapper,
Validators: []TraitDefValidator{ Validators: []TraitDefValidator{
TraitDefValidatorFn(ValidateDefinitionReference), TraitDefValidatorFn(ValidateDefinitionReference),
// add more validators here // add more validators here
}, },
}}) }})
return nil
} }
// ValidateDefinitionReference validates whether the trait definition is valid if // ValidateDefinitionReference validates whether the trait definition is valid if
......
...@@ -5,11 +5,12 @@ import ( ...@@ -5,11 +5,12 @@ import (
"net/http" "net/http"
"time" "time"
"github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/pkg/errors" "github.com/pkg/errors"
ctrl "sigs.k8s.io/controller-runtime" ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/client"
"github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper"
) )
...@@ -18,11 +19,11 @@ type APIServer struct { ...@@ -18,11 +19,11 @@ type APIServer struct {
server *http.Server server *http.Server
KubeClient client.Client KubeClient client.Client
dm discoverymapper.DiscoveryMapper dm discoverymapper.DiscoveryMapper
c types.Args c common.Args
} }
// New will create APIServer // New will create APIServer
func New(c types.Args, port, staticPath string) (*APIServer, error) { func New(c common.Args, port, staticPath string) (*APIServer, error) {
newClient, err := c.GetClient() newClient, err := c.GetClient()
if err != nil { if err != nil {
return nil, err return nil, err
......
...@@ -112,7 +112,7 @@ func (s *APIServer) CreateApplication(c *gin.Context) { ...@@ -112,7 +112,7 @@ func (s *APIServer) CreateApplication(c *gin.Context) {
util.HandleError(c, util.StatusInternalServerError, err.Error()) util.HandleError(c, util.StatusInternalServerError, err.Error())
return return
} }
err = o.BaseAppFileRun(buildResult, data, s.dm) err = o.BaseAppFileRun(buildResult, data, s.c)
if err != nil { if err != nil {
util.HandleError(c, util.StatusInternalServerError, err.Error()) util.HandleError(c, util.StatusInternalServerError, err.Error())
return return
......
...@@ -18,7 +18,6 @@ import ( ...@@ -18,7 +18,6 @@ import (
"github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/appfile" "github.com/oam-dev/kubevela/pkg/appfile"
"github.com/oam-dev/kubevela/pkg/controller/utils" "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" util2 "github.com/oam-dev/kubevela/pkg/oam/util"
"github.com/oam-dev/kubevela/pkg/utils/common" "github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/pkg/utils/util" "github.com/oam-dev/kubevela/pkg/utils/util"
...@@ -32,11 +31,20 @@ const ( ...@@ -32,11 +31,20 @@ const (
) )
// ApplyTerraform deploys addon resources // ApplyTerraform deploys addon resources
func ApplyTerraform(app *v1alpha2.Application, k8sClient client.Client, ioStream util.IOStreams, namespace string, dm discoverymapper.DiscoveryMapper) ([]v1alpha2.ApplicationComponent, error) { func ApplyTerraform(app *v1alpha2.Application, k8sClient client.Client, ioStream util.IOStreams, namespace string, args common.Args) ([]v1alpha2.ApplicationComponent, error) {
dm, err := args.GetDiscoveryMapper()
if err != nil {
return nil, err
}
pd, err := args.GetPackageDiscover()
if err != nil {
return nil, err
}
// TODO(zzxwill) Need to check whether authentication credentials of a specific cloud provider are exported as environment variables, like `ALICLOUD_ACCESS_KEY` // TODO(zzxwill) Need to check whether authentication credentials of a specific cloud provider are exported as environment variables, like `ALICLOUD_ACCESS_KEY`
var nativeVelaComponents []v1alpha2.ApplicationComponent var nativeVelaComponents []v1alpha2.ApplicationComponent
// parse template // parse template
appParser := appfile.NewApplicationParser(k8sClient, dm) appParser := appfile.NewApplicationParser(k8sClient, dm, pd)
ctx := util2.SetNamespaceInCtx(context.Background(), namespace) ctx := util2.SetNamespaceInCtx(context.Background(), namespace)
appFile, err := appParser.GenerateAppFile(ctx, app.Name, app) appFile, err := appParser.GenerateAppFile(ctx, app.Name, app)
......
...@@ -10,7 +10,7 @@ import ( ...@@ -10,7 +10,7 @@ import (
"k8s.io/apimachinery/pkg/runtime" "k8s.io/apimachinery/pkg/runtime"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/pkg/oam/discoverymapper" "github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/pkg/utils/util" "github.com/oam-dev/kubevela/pkg/utils/util"
) )
...@@ -25,9 +25,8 @@ var _ = It("Test ApplyTerraform", func() { ...@@ -25,9 +25,8 @@ var _ = It("Test ApplyTerraform", func() {
}}, }},
} }
ioStream := util.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr} ioStream := util.IOStreams{In: os.Stdin, Out: os.Stdout, ErrOut: os.Stderr}
dm, _ := discoverymapper.New(cfg) _, err := ApplyTerraform(app, k8sClient, ioStream, addonNamespace, common.Args{Config: cfg})
_, err := ApplyTerraform(app, k8sClient, ioStream, addonNamespace, dm) Expect(err).Should(BeNil())
Expect(err).ShouldNot(BeNil())
}) })
var _ = Describe("Test generateSecretFromTerraformOutput", func() { var _ = Describe("Test generateSecretFromTerraformOutput", func() {
......
...@@ -12,12 +12,13 @@ import ( ...@@ -12,12 +12,13 @@ import (
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/apis/types" "github.com/oam-dev/kubevela/apis/types"
"github.com/oam-dev/kubevela/pkg/utils/common"
"github.com/oam-dev/kubevela/references/appfile/api" "github.com/oam-dev/kubevela/references/appfile/api"
"github.com/oam-dev/kubevela/references/appfile/template" "github.com/oam-dev/kubevela/references/appfile/template"
) )
// NewEmptyApplication new empty application, only set tm // NewEmptyApplication new empty application, only set tm
func NewEmptyApplication(namespace string, c types.Args) (*api.Application, error) { func NewEmptyApplication(namespace string, c common.Args) (*api.Application, error) {
tm, err := template.Load(namespace, c) tm, err := template.Load(namespace, c)
if err != nil { if err != nil {
return nil, err return nil, err
...@@ -54,7 +55,7 @@ func Validate(app *api.Application) error { ...@@ -54,7 +55,7 @@ func Validate(app *api.Application) error {
} }
// LoadApplication will load application from cluster. // LoadApplication will load application from cluster.
func LoadApplication(namespace, appName string, c types.Args) (*v1alpha2.Application, error) { func LoadApplication(namespace, appName string, c common.Args) (*v1alpha2.Application, error) {
newClient, err := c.GetClient() newClient, err := c.GetClient()
if err != nil { if err != nil {
return nil, err return nil, err
......
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