mirror of
https://github.com/kubevela/kubevela.git
synced 2026-08-18 20:17:04 +00:00
add hpa trait and fix template without params (#1279)
This commit is contained in:
+44
-1
@@ -86,7 +86,50 @@ Hence, the `settings` section of `backend` only supports two parameters: `image`
|
||||
|
||||
The similar extensible abstraction mechanism also applies to traits. For example, `name: autoscaler` in `frontend` means its trait specification (i.e. `properties` section) will be enforced by a `TraitDefinition` object named `autoscaler` as below:
|
||||
|
||||
> TBD: a autoscaler TraitDefinition (HPA)
|
||||
```yaml
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: "configure k8s HPA for Deployment"
|
||||
name: hpa
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- webservice
|
||||
- worker
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
outputs: hpa: {
|
||||
apiVersion: "autoscaling/v2beta2"
|
||||
kind: "HorizontalPodAutoscaler"
|
||||
metadata: name: context.name
|
||||
spec: {
|
||||
scaleTargetRef: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
name: context.name
|
||||
}
|
||||
minReplicas: parameter.min
|
||||
maxReplicas: parameter.max
|
||||
metrics: [{
|
||||
type: "Resource"
|
||||
resource: {
|
||||
name: "cpu"
|
||||
target: {
|
||||
type: "Utilization"
|
||||
averageUtilization: parameter.cpuUtil
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
min: *1 | int
|
||||
max: *10 | int
|
||||
cpuUtil: *50 | int
|
||||
}
|
||||
```
|
||||
|
||||
All the definition objects are expected to be defined and installed by platform team. The end users will only focus on `Application` resource (either render it by tools or author it manually).
|
||||
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
outputs: hpa: {
|
||||
apiVersion: "autoscaling/v2beta2"
|
||||
kind: "HorizontalPodAutoscaler"
|
||||
metadata: name: context.name
|
||||
spec: {
|
||||
scaleTargetRef: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
name: context.name
|
||||
}
|
||||
minReplicas: parameter.min
|
||||
maxReplicas: parameter.max
|
||||
metrics: [{
|
||||
type: "Resource"
|
||||
resource: {
|
||||
name: "cpu"
|
||||
target: {
|
||||
type: "Utilization"
|
||||
averageUtilization: parameter.cpuUtil
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
min: *1 | int
|
||||
max: *10 | int
|
||||
cpuUtil: *50 | int
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/description: "configure k8s HPA for Deployment"
|
||||
name: hpa
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- webservice
|
||||
- worker
|
||||
schematic:
|
||||
cue:
|
||||
template: |
|
||||
outputs: hpa: {
|
||||
apiVersion: "autoscaling/v2beta2"
|
||||
kind: "HorizontalPodAutoscaler"
|
||||
metadata: name: context.name
|
||||
spec: {
|
||||
scaleTargetRef: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
name: context.name
|
||||
}
|
||||
minReplicas: parameter.min
|
||||
maxReplicas: parameter.max
|
||||
metrics: [{
|
||||
type: "Resource"
|
||||
resource: {
|
||||
name: "cpu"
|
||||
target: {
|
||||
type: "Utilization"
|
||||
averageUtilization: parameter.cpuUtil
|
||||
}
|
||||
}
|
||||
}]
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
min: *1 | int
|
||||
max: *10 | int
|
||||
cpuUtil: *50 | int
|
||||
}
|
||||
|
||||
@@ -69,15 +69,19 @@ func (wd *workloadDef) Complete(ctx process.Context, abstractTemplate string, pa
|
||||
if err := bi.AddFile("-", abstractTemplate); err != nil {
|
||||
return errors.WithMessagef(err, "invalid cue template of workload %s", wd.name)
|
||||
}
|
||||
var paramFile = "parameter: {}"
|
||||
if params != nil {
|
||||
bt, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return errors.WithMessagef(err, "marshal parameter of workload %s", wd.name)
|
||||
}
|
||||
if err := bi.AddFile("parameter", fmt.Sprintf("parameter: %s", string(bt))); err != nil {
|
||||
return errors.WithMessagef(err, "invalid parameter of workload %s", wd.name)
|
||||
if string(bt) != "null" {
|
||||
paramFile = fmt.Sprintf("parameter: %s", string(bt))
|
||||
}
|
||||
}
|
||||
if err := bi.AddFile("parameter", paramFile); err != nil {
|
||||
return errors.WithMessagef(err, "invalid parameter of workload %s", wd.name)
|
||||
}
|
||||
|
||||
if err := bi.AddFile("-", ctx.BaseContextFile()); err != nil {
|
||||
return err
|
||||
@@ -248,16 +252,19 @@ func (td *traitDef) Complete(ctx process.Context, abstractTemplate string, param
|
||||
if err := bi.AddFile("-", abstractTemplate); err != nil {
|
||||
return errors.WithMessagef(err, "invalid template of trait %s", td.name)
|
||||
}
|
||||
var paramFile = "parameter: {}"
|
||||
if params != nil {
|
||||
bt, err := json.Marshal(params)
|
||||
if err != nil {
|
||||
return errors.WithMessagef(err, "marshal parameter of trait %s", td.name)
|
||||
}
|
||||
if err := bi.AddFile("parameter", fmt.Sprintf("parameter: %s", string(bt))); err != nil {
|
||||
return errors.WithMessagef(err, "invalid parameter of trait %s", td.name)
|
||||
if string(bt) != "null" {
|
||||
paramFile = fmt.Sprintf("parameter: %s", string(bt))
|
||||
}
|
||||
}
|
||||
|
||||
if err := bi.AddFile("parameter", paramFile); err != nil {
|
||||
return errors.WithMessagef(err, "invalid parameter of trait %s", td.name)
|
||||
}
|
||||
if err := bi.AddFile("context", ctx.BaseContextFile()); err != nil {
|
||||
return errors.WithMessagef(err, "invalid context of trait %s", td.name)
|
||||
}
|
||||
|
||||
@@ -103,6 +103,23 @@ parameter: {
|
||||
},
|
||||
expectObj: &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{"name": "test", "annotations": map[string]interface{}{"revision.oam.dev": "myapp-v1"}}, "spec": map[string]interface{}{"replicas": int64(2)}}},
|
||||
},
|
||||
{
|
||||
workloadTemplate: `
|
||||
output:{
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
metadata: {
|
||||
name: context.name
|
||||
}
|
||||
spec: replicas: parameter.replicas
|
||||
}
|
||||
parameter: {
|
||||
replicas: *1 | int
|
||||
}
|
||||
`,
|
||||
params: nil,
|
||||
expectObj: &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "apps/v1", "kind": "Deployment", "metadata": map[string]interface{}{"name": "test"}, "spec": map[string]interface{}{"replicas": int64(1)}}},
|
||||
},
|
||||
}
|
||||
|
||||
for _, v := range testCases {
|
||||
@@ -496,6 +513,57 @@ parameter: {
|
||||
"t2ingress": &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "extensions/v1beta1", "kind": "Ingress"}},
|
||||
},
|
||||
},
|
||||
"outputs trait with no params": {
|
||||
traitTemplate: `
|
||||
outputs: hpa: {
|
||||
apiVersion: "autoscaling/v2beta2"
|
||||
kind: "HorizontalPodAutoscaler"
|
||||
metadata: name: context.name
|
||||
spec: {
|
||||
minReplicas: parameter.min
|
||||
maxReplicas: parameter.max
|
||||
}
|
||||
}
|
||||
parameter: {
|
||||
min: *1 | int
|
||||
max: *10 | int
|
||||
}`,
|
||||
params: nil,
|
||||
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"}},
|
||||
},
|
||||
"t2hpa": &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": "autoscaling/v2beta2", "kind": "HorizontalPodAutoscaler",
|
||||
"metadata": map[string]interface{}{"name": "test"},
|
||||
"spec": map[string]interface{}{"maxReplicas": int64(10), "minReplicas": int64(1)}}},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for cassinfo, v := range tds {
|
||||
|
||||
Reference in New Issue
Block a user