mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-27 16:17:34 +00:00
289 lines
6.5 KiB
Go
289 lines
6.5 KiB
Go
package util
|
|
|
|
import (
|
|
"context"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
"cuelang.org/go/cue"
|
|
"github.com/crossplane/crossplane-runtime/pkg/test"
|
|
"k8s.io/apimachinery/pkg/runtime"
|
|
ktypes "k8s.io/apimachinery/pkg/types"
|
|
|
|
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
|
|
"github.com/oam-dev/kubevela/apis/types"
|
|
)
|
|
|
|
func TestLoadWorkloadTemplate(t *testing.T) {
|
|
cueTemplate := `
|
|
context: {
|
|
name: "test"
|
|
}
|
|
output: {
|
|
apiVersion: "apps/v1"
|
|
kind: "Deployment"
|
|
spec: {
|
|
selector: matchLabels: {
|
|
"app.oam.dev/component": context.name
|
|
}
|
|
|
|
template: {
|
|
metadata: labels: {
|
|
"app.oam.dev/component": context.name
|
|
}
|
|
|
|
spec: {
|
|
containers: [{
|
|
name: context.name
|
|
image: parameter.image
|
|
|
|
if parameter["cmd"] != _|_ {
|
|
command: parameter.cmd
|
|
}
|
|
}]
|
|
}
|
|
}
|
|
|
|
selector:
|
|
matchLabels:
|
|
"app.oam.dev/component": context.name
|
|
}
|
|
}
|
|
|
|
parameter: {
|
|
// +usage=Which image would you like to use for your service
|
|
// +short=i
|
|
image: string
|
|
|
|
cmd?: [...string]
|
|
}
|
|
`
|
|
|
|
var workloadDefintion = `
|
|
apiVersion: core.oam.dev/v1alpha2
|
|
kind: WorkloadDefinition
|
|
metadata:
|
|
name: worker
|
|
namespace: default
|
|
annotations:
|
|
definition.oam.dev/description: "Long-running scalable backend worker without network endpoint"
|
|
spec:
|
|
definitionRef:
|
|
name: deployments.apps
|
|
extension:
|
|
template: |
|
|
` + cueTemplate
|
|
|
|
// Create mock client
|
|
tclient := test.MockClient{
|
|
MockGet: func(ctx context.Context, key ktypes.NamespacedName, obj runtime.Object) error {
|
|
switch o := obj.(type) {
|
|
case *v1alpha2.WorkloadDefinition:
|
|
wd, err := UnMarshalStringToWorkloadDefinition(workloadDefintion)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*o = *wd
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
temp, err := LoadTemplate(context.TODO(), &tclient, "worker", types.TypeWorkload)
|
|
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
var r cue.Runtime
|
|
inst, err := r.Compile("-", temp.TemplateStr)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
instDest, err := r.Compile("-", cueTemplate)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
s1, _ := inst.Value().String()
|
|
s2, _ := instDest.Value().String()
|
|
if s1 != s2 {
|
|
t.Errorf("parsered template is not correct")
|
|
}
|
|
}
|
|
|
|
func TestLoadTraitTemplate(t *testing.T) {
|
|
cueTemplate := `
|
|
parameter: {
|
|
domain: string
|
|
http: [string]: int
|
|
}
|
|
context: {
|
|
name: "test"
|
|
}
|
|
// trait template can have multiple outputs in one trait
|
|
outputs: service: {
|
|
apiVersion: "v1"
|
|
kind: "Service"
|
|
metadata:
|
|
name: context.name
|
|
spec: {
|
|
selector:
|
|
"app.oam.dev/component": context.name
|
|
ports: [
|
|
for k, v in parameter.http {
|
|
port: v
|
|
targetPort: v
|
|
},
|
|
]
|
|
}
|
|
}
|
|
|
|
outputs: ingress: {
|
|
apiVersion: "networking.k8s.io/v1beta1"
|
|
kind: "Ingress"
|
|
metadata:
|
|
name: context.name
|
|
spec: {
|
|
rules: [{
|
|
host: parameter.domain
|
|
http: {
|
|
paths: [
|
|
for k, v in parameter.http {
|
|
path: k
|
|
backend: {
|
|
serviceName: context.name
|
|
servicePort: v
|
|
}
|
|
},
|
|
]
|
|
}
|
|
}]
|
|
}
|
|
}
|
|
`
|
|
|
|
var traitDefintion = `
|
|
apiVersion: core.oam.dev/v1alpha2
|
|
kind: TraitDefinition
|
|
metadata:
|
|
annotations:
|
|
definition.oam.dev/description: "Configures K8s ingress and service to enable web traffic for your service.
|
|
Please use route trait in cap center for advanced usage."
|
|
name: ingress
|
|
namespace: default
|
|
spec:
|
|
status:
|
|
customStatus: |-
|
|
if len(context.outputs.ingress.status.loadBalancer.ingress) > 0 {
|
|
message: "Visiting URL: " + context.outputs.ingress.spec.rules[0].host + ", IP: " + context.outputs.ingress.status.loadBalancer.ingress[0].ip
|
|
}
|
|
if len(context.outputs.ingress.status.loadBalancer.ingress) == 0 {
|
|
message: "No loadBalancer found, visiting by using 'vela port-forward " + context.appName + " --route'\n"
|
|
}
|
|
healthPolicy: |
|
|
isHealth: len(context.outputs.service.spec.clusterIP) > 0
|
|
appliesToWorkloads:
|
|
- webservice
|
|
- worker
|
|
schematic:
|
|
cue:
|
|
template: |
|
|
` + cueTemplate
|
|
|
|
// Create mock client
|
|
tclient := test.MockClient{
|
|
MockGet: func(ctx context.Context, key ktypes.NamespacedName, obj runtime.Object) error {
|
|
switch o := obj.(type) {
|
|
case *v1alpha2.TraitDefinition:
|
|
wd, err := UnMarshalStringToTraitDefinition(traitDefintion)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
*o = *wd
|
|
}
|
|
return nil
|
|
},
|
|
}
|
|
|
|
temp, err := LoadTemplate(context.TODO(), &tclient, "ingress", types.TypeTrait)
|
|
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
var r cue.Runtime
|
|
inst, err := r.Compile("-", temp.TemplateStr)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
instDest, err := r.Compile("-", cueTemplate)
|
|
if err != nil {
|
|
t.Error(err)
|
|
return
|
|
}
|
|
s1, _ := inst.Value().String()
|
|
s2, _ := instDest.Value().String()
|
|
if s1 != s2 {
|
|
t.Errorf("parsered template is not correct")
|
|
}
|
|
}
|
|
|
|
func TestNewTemplate(t *testing.T) {
|
|
testCases := map[string]struct {
|
|
tmp *v1alpha2.Schematic
|
|
status *v1alpha2.Status
|
|
ext *runtime.RawExtension
|
|
exp *Template
|
|
}{
|
|
"only tmp": {
|
|
tmp: &v1alpha2.Schematic{CUE: &v1alpha2.CUE{Template: "t1"}},
|
|
exp: &Template{
|
|
TemplateStr: "t1",
|
|
},
|
|
},
|
|
"no tmp,but has extension": {
|
|
ext: &runtime.RawExtension{Raw: []byte(`{"template":"t1"}`)},
|
|
exp: &Template{
|
|
TemplateStr: "t1",
|
|
},
|
|
},
|
|
"no tmp,but has extension without temp": {
|
|
ext: &runtime.RawExtension{Raw: []byte(`{"template":{"t1":"t2"}}`)},
|
|
exp: &Template{
|
|
TemplateStr: "",
|
|
},
|
|
},
|
|
"tmp with status": {
|
|
tmp: &v1alpha2.Schematic{CUE: &v1alpha2.CUE{Template: "t1"}},
|
|
status: &v1alpha2.Status{
|
|
CustomStatus: "s1",
|
|
HealthPolicy: "h1",
|
|
},
|
|
exp: &Template{
|
|
TemplateStr: "t1",
|
|
CustomStatus: "s1",
|
|
Health: "h1",
|
|
},
|
|
},
|
|
"no tmp only status": {
|
|
status: &v1alpha2.Status{
|
|
CustomStatus: "s1",
|
|
HealthPolicy: "h1",
|
|
},
|
|
exp: &Template{
|
|
CustomStatus: "s1",
|
|
Health: "h1",
|
|
},
|
|
},
|
|
}
|
|
for reason, casei := range testCases {
|
|
gtmp, err := NewTemplate(casei.tmp, casei.status, casei.ext)
|
|
assert.NoError(t, err, reason)
|
|
assert.Equal(t, gtmp, casei.exp, reason)
|
|
}
|
|
}
|