Merge pull request #1352 from wonderflow/hongchaodeng-revlabel

add AppRevision label to cuetemplate
This commit is contained in:
Hongchao Deng
2021-03-29 05:26:52 -07:00
committed by GitHub
9 changed files with 123 additions and 70 deletions
+1 -2
View File
@@ -151,7 +151,6 @@ After the `Application` resource is applied to Kubernetes cluster, the KubeVela
|`app.oam.dev/name=<app name>` | The name of the application it belongs to |
|`app.oam.dev/component=<component name>` | The name of the component it belongs to |
|`trait.oam.dev/resource=<name of trait resource instance>` | The name of trait resource instance |
> TBD: the revision names and labels for resource instances are currently work in progress.
|`app.oam.dev/appRevision=<name of app revision>` | The name of the application revision it belongs to |
> TBD: a demo for kubectl apply above Application CR and show full detailed underlying resources.
+12 -2
View File
@@ -175,7 +175,7 @@ spec:
KubeVela allows you to reference the runtime information of your application via `conext` keyword.
The most widely used context is application name(`context.appName`) and component name(`context.name`).
The most widely used context is application name(`context.appName`) component name(`context.name`).
```cue
context: {
@@ -204,7 +204,17 @@ output: {
> Note that `context` information are auto-injected before resources are applied to target cluster.
> TBD: full available information in CUE `context`.
### Full available information in CUE `context`
| Context Variable | Description |
| :--: | :---------: |
| `context.appRevision` | The revision of the application |
| `context.appName` | The name of the application |
| `context.name` | The name of the component of the application |
| `context.namespace` | The namespace of the application |
| `context.output` | The rendered workload API resource of the component, this usually used in trait |
| `context.outputs.<resourceName>` | The rendered trait API resource of the component, this usually used in trait |
## Composition
+1 -1
View File
@@ -90,7 +90,7 @@
$ kubectl apply -f appdeployment-2-traffic.yaml
```
Note that for traffic split to work, your must have the following labels set in pods (This is automatically set in default `webservice` workload template):
Note that for traffic split to work, your must have the following labels set in pods (This is automatically set by KubeVela Revision Mechanism):
```shell
"app.oam.dev/component": "testsvc"
+3 -11
View File
@@ -534,12 +534,8 @@ func evalWorkloadWithContext(pCtx process.Context, wl *Workload, appName, compNa
return nil, nil, errors.Wrapf(err, "evaluate base template component=%s app=%s", compName, appName)
}
labels := map[string]string{
oam.WorkloadTypeLabel: wl.Type,
oam.LabelAppName: appName,
oam.LabelAppComponent: compName,
}
util.AddLabels(componentWorkload, labels)
var commonLabels = definition.GetCommonLabels(pCtx.BaseContextLabels())
util.AddLabels(componentWorkload, util.MergeMapOverrideWithDst(commonLabels, map[string]string{oam.WorkloadTypeLabel: wl.Type}))
component := &v1alpha2.Component{}
// we need to marshal the workload to byte array before sending them to the k8s
@@ -551,11 +547,7 @@ func evalWorkloadWithContext(pCtx process.Context, wl *Workload, appName, compNa
if err != nil {
return nil, nil, errors.Wrapf(err, "evaluate trait=%s template for component=%s app=%s", assist.Name, compName, appName)
}
labels := map[string]string{
oam.TraitTypeLabel: assist.Type,
oam.LabelAppName: appName,
oam.LabelAppComponent: compName,
}
labels := util.MergeMapOverrideWithDst(commonLabels, map[string]string{oam.TraitTypeLabel: assist.Type})
if assist.Name != "" {
labels[oam.TraitResource] = assist.Name
}
+29 -21
View File
@@ -287,7 +287,8 @@ var _ = Describe("Test appFile parser", func() {
It("application without-trait will only create appfile with workload", func() {
// TestApp is test data
var TestApp = &Appfile{
Name: "test",
RevisionName: "test-v1",
Name: "test",
Workloads: []*Workload{
{
Name: "myweb",
@@ -385,10 +386,11 @@ var _ = Describe("Test appFile parser", func() {
"kind": "ManualScalerTrait",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app.oam.dev/component": "myweb",
"app.oam.dev/name": "test",
"trait.oam.dev/type": "scaler",
"trait.oam.dev/resource": "scaler",
"app.oam.dev/component": "myweb",
"app.oam.dev/appRevision": "test-v1",
"app.oam.dev/name": "test",
"trait.oam.dev/type": "scaler",
"trait.oam.dev/resource": "scaler",
},
},
"spec": map[string]interface{}{"replicaCount": int64(10)},
@@ -443,9 +445,10 @@ var _ = Describe("Test appFile parser", func() {
"kind": "Deployment",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"workload.oam.dev/type": "worker",
"app.oam.dev/component": "myweb",
"app.oam.dev/name": "test",
"workload.oam.dev/type": "worker",
"app.oam.dev/component": "myweb",
"app.oam.dev/appRevision": "test-v1",
"app.oam.dev/name": "test",
},
},
"spec": map[string]interface{}{
@@ -507,7 +510,8 @@ var _ = Describe("Test appfile parser to parse helm module", func() {
It("Test application containing helm module", func() {
appFile := &Appfile{
Name: appName,
Name: appName,
RevisionName: appName + "-v1",
Workloads: []*Workload{
{
Name: compName,
@@ -571,10 +575,11 @@ var _ = Describe("Test appfile parser to parse helm module", func() {
"kind": "ManualScalerTrait",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app.oam.dev/component": compName,
"app.oam.dev/name": appName,
"trait.oam.dev/type": "scaler",
"trait.oam.dev/resource": "scaler",
"app.oam.dev/component": compName,
"app.oam.dev/name": appName,
"trait.oam.dev/type": "scaler",
"trait.oam.dev/resource": "scaler",
"app.oam.dev/appRevision": appName + "-v1",
},
},
"spec": map[string]interface{}{"replicaCount": int64(10)},
@@ -655,9 +660,10 @@ var _ = Describe("Test appfile parser to parse helm module", func() {
"kind": "Deployment",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"workload.oam.dev/type": "webapp-chart",
"app.oam.dev/component": compName,
"app.oam.dev/name": appName,
"workload.oam.dev/type": "webapp-chart",
"app.oam.dev/component": compName,
"app.oam.dev/name": appName,
"app.oam.dev/appRevision": appName + "-v1",
},
},
}),
@@ -719,7 +725,8 @@ spec:
}
var testAppfile = func() *Appfile {
return &Appfile{
Name: appName,
RevisionName: appName + "-v1",
Name: appName,
Workloads: []*Workload{
{
Name: compName,
@@ -780,10 +787,11 @@ spec:
"kind": "ManualScalerTrait",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"app.oam.dev/component": compName,
"app.oam.dev/name": appName,
"trait.oam.dev/type": "scaler",
"trait.oam.dev/resource": "scaler",
"app.oam.dev/component": compName,
"app.oam.dev/name": appName,
"app.oam.dev/appRevision": appName + "-v1",
"trait.oam.dev/type": "scaler",
"trait.oam.dev/resource": "scaler",
},
},
"spec": map[string]interface{}{"replicaCount": int64(10)},
@@ -26,8 +26,6 @@ import (
"strconv"
"time"
common2 "github.com/oam-dev/kubevela/pkg/utils/common"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -37,9 +35,11 @@ import (
"github.com/stretchr/testify/assert"
v1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
v1beta12 "k8s.io/api/networking/v1beta1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/utils/pointer"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/reconcile"
@@ -50,6 +50,7 @@ import (
"github.com/oam-dev/kubevela/pkg/controller/utils"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/util"
common2 "github.com/oam-dev/kubevela/pkg/utils/common"
)
// TODO: Refactor the tests to not copy and paste duplicated code 10 times
@@ -126,9 +127,10 @@ var _ = Describe("Test Application Controller", func() {
},
ObjectMeta: metav1.ObjectMeta{
Labels: map[string]string{
"workload.oam.dev/type": "worker",
"app.oam.dev/component": compName,
"app.oam.dev/name": appName,
"workload.oam.dev/type": "worker",
"app.oam.dev/component": compName,
"app.oam.dev/name": appName,
"app.oam.dev/appRevision": appName + "-v1",
},
},
Spec: v1.DeploymentSpec{
@@ -164,10 +166,11 @@ var _ = Describe("Test Application Controller", func() {
"kind": "ManualScalerTrait",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"trait.oam.dev/type": "scaler",
"app.oam.dev/component": compName,
"app.oam.dev/name": appName,
"trait.oam.dev/resource": "scaler",
"trait.oam.dev/type": "scaler",
"app.oam.dev/component": compName,
"app.oam.dev/name": appName,
"app.oam.dev/appRevision": appName + "-v1",
"trait.oam.dev/resource": "scaler",
},
},
"spec": map[string]interface{}{
@@ -557,10 +560,11 @@ spec:
"kind": "Service",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"trait.oam.dev/type": "AuxiliaryWorkload",
"app.oam.dev/name": "app-with-composedworkload-trait",
"app.oam.dev/component": "myweb-composed-3",
"trait.oam.dev/resource": "service",
"trait.oam.dev/type": "AuxiliaryWorkload",
"app.oam.dev/name": "app-with-composedworkload-trait",
"app.oam.dev/appRevision": "app-with-composedworkload-trait-v1",
"app.oam.dev/component": "myweb-composed-3",
"trait.oam.dev/resource": "service",
},
},
"spec": map[string]interface{}{
@@ -754,7 +758,7 @@ spec:
fmt.Println(cmp.Diff(expDeployment6, gotD2))
Expect(gotD2).Should(BeEquivalentTo(expDeployment6))
By("update component5 with new spec, rename component6 it should create new component ")
By("Update Application with new revision, component5 with new spec, rename component6 it should create new component ")
curApp.SetNamespace(app.Namespace)
curApp.Spec.Components[0] = v1beta1.ApplicationComponent{
@@ -809,6 +813,7 @@ spec:
}, component5)).Should(BeNil())
Expect(json.Unmarshal(component5.Spec.Workload.Raw, gotD)).Should(BeNil())
expDeployment.Spec.Template.Spec.Containers[0].Image = "busybox3"
expDeployment.Labels["app.oam.dev/appRevision"] = app.Name + "-v2"
Expect(gotD).Should(BeEquivalentTo(expDeployment))
expDeployment7 := getExpDeployment("myweb7", app.Name)
@@ -820,6 +825,7 @@ spec:
Expect(component7.ObjectMeta.Labels).Should(BeEquivalentTo(map[string]string{oam.LabelAppName: app.Name}))
gotD3 := &v1.Deployment{}
Expect(json.Unmarshal(component7.Spec.Workload.Raw, gotD3)).Should(BeNil())
expDeployment7.Labels["app.oam.dev/appRevision"] = app.Name + "-v2"
fmt.Println(cmp.Diff(gotD3, expDeployment7))
Expect(gotD3).Should(BeEquivalentTo(expDeployment7))
Expect(k8sClient.Delete(ctx, app)).Should(BeNil())
@@ -1134,10 +1140,11 @@ spec:
"kind": "ConfigMap",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"trait.oam.dev/type": "AuxiliaryWorkload",
"app.oam.dev/component": compName,
"app.oam.dev/name": app.Name,
"trait.oam.dev/resource": "gameconfig",
"trait.oam.dev/type": "AuxiliaryWorkload",
"app.oam.dev/component": compName,
"app.oam.dev/name": app.Name,
"trait.oam.dev/resource": "gameconfig",
"app.oam.dev/appRevision": app.Name + "-v1",
},
},
"data": map[string]interface{}{
@@ -1154,10 +1161,11 @@ spec:
"kind": "Ingress",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"trait.oam.dev/type": "ingress",
"trait.oam.dev/resource": "ingress",
"app.oam.dev/component": compName,
"app.oam.dev/name": app.Name,
"trait.oam.dev/type": "ingress",
"trait.oam.dev/resource": "ingress",
"app.oam.dev/component": compName,
"app.oam.dev/name": app.Name,
"app.oam.dev/appRevision": app.Name + "-v1",
},
},
"spec": map[string]interface{}{
@@ -1177,10 +1185,11 @@ spec:
"kind": "Service",
"metadata": map[string]interface{}{
"labels": map[string]interface{}{
"trait.oam.dev/type": "ingress",
"trait.oam.dev/resource": "service",
"app.oam.dev/component": compName,
"app.oam.dev/name": app.Name,
"trait.oam.dev/type": "ingress",
"trait.oam.dev/resource": "service",
"app.oam.dev/component": compName,
"app.oam.dev/name": app.Name,
"app.oam.dev/appRevision": app.Name + "-v1",
},
},
"spec": map[string]interface{}{
@@ -1379,8 +1388,41 @@ spec:
}, appRevision)).Should(BeNil())
appConfig, err := util.RawExtension2AppConfig(appRevision.Spec.ApplicationConfiguration)
Expect(err).ShouldNot(HaveOccurred())
Expect(string(appConfig.Spec.Components[0].Traits[0].Trait.Raw)).Should(BeEquivalentTo("{\"apiVersion\":\"v1\",\"kind\":\"Service\",\"metadata\":{\"labels\":{\"app.oam.dev/component\":\"myweb\",\"app.oam.dev/name\":\"app-import-pkg\",\"trait.oam.dev/resource\":\"service\",\"trait.oam.dev/type\":\"ingress-import\"},\"name\":\"myweb\"},\"spec\":{\"ports\":[{\"port\":80,\"targetPort\":80}],\"selector\":{\"app.oam.dev/component\":\"myweb\"}}}"))
Expect(string(appConfig.Spec.Components[0].Traits[1].Trait.Raw)).Should(BeEquivalentTo("{\"apiVersion\":\"networking.k8s.io/v1beta1\",\"kind\":\"Ingress\",\"metadata\":{\"labels\":{\"app.oam.dev/component\":\"myweb\",\"app.oam.dev/name\":\"app-import-pkg\",\"trait.oam.dev/resource\":\"ingress\",\"trait.oam.dev/type\":\"ingress-import\"},\"name\":\"myweb\"},\"spec\":{\"rules\":[{\"host\":\"abc.com\",\"http\":{\"paths\":[{\"backend\":{\"serviceName\":\"myweb\",\"servicePort\":80},\"path\":\"/\"}]}}]}}"))
var gotSvc corev1.Service
Expect(json.Unmarshal(appConfig.Spec.Components[0].Traits[0].Trait.Raw, &gotSvc)).ShouldNot(HaveOccurred())
Expect(cmp.Diff(&gotSvc, &corev1.Service{
TypeMeta: metav1.TypeMeta{Kind: "Service", APIVersion: "v1"},
ObjectMeta: metav1.ObjectMeta{
Name: "myweb",
Labels: map[string]string{
"app.oam.dev/component": "myweb",
"app.oam.dev/name": "app-import-pkg",
"trait.oam.dev/resource": "service",
"trait.oam.dev/type": "ingress-import",
"app.oam.dev/appRevision": "app-import-pkg-v1",
}},
Spec: corev1.ServiceSpec{
Ports: []corev1.ServicePort{{Port: 80, TargetPort: intstr.FromInt(80)}},
Selector: map[string]string{"app.oam.dev/component": "myweb"},
}})).Should(BeEquivalentTo(""))
var gotIngress v1beta12.Ingress
Expect(json.Unmarshal(appConfig.Spec.Components[0].Traits[1].Trait.Raw, &gotIngress)).ShouldNot(HaveOccurred())
Expect(cmp.Diff(&gotIngress, &v1beta12.Ingress{
TypeMeta: metav1.TypeMeta{Kind: "Ingress", APIVersion: "networking.k8s.io/v1beta1"},
ObjectMeta: metav1.ObjectMeta{
Name: "myweb",
Labels: map[string]string{
"app.oam.dev/component": "myweb",
"app.oam.dev/name": "app-import-pkg",
"trait.oam.dev/resource": "ingress",
"trait.oam.dev/type": "ingress-import",
"app.oam.dev/appRevision": "app-import-pkg-v1",
}},
Spec: v1beta12.IngressSpec{Rules: []v1beta12.IngressRule{{Host: "abc.com",
IngressRuleValue: v1beta12.IngressRuleValue{HTTP: &v1beta12.HTTPIngressRuleValue{Paths: []v1beta12.HTTPIngressPath{{
Path: "/",
Backend: v1beta12.IngressBackend{ServiceName: "myweb", ServicePort: intstr.FromInt(80)}}}}}}},
}})).Should(BeEquivalentTo(""))
By("Check ApplicationContext created")
appContext := &v1alpha2.ApplicationContext{}
@@ -110,6 +110,7 @@ func (h *appHandler) apply(ctx context.Context, appRev *v1beta1.ApplicationRevis
// don't create components and AC if revision-only annotation is set
if ac.Annotations[oam.AnnotationAppRevisionOnly] == "true" {
h.FinalizeAppRevision(appRev, ac, comps)
return h.createOrUpdateAppRevision(ctx, appRev)
}
+5 -4
View File
@@ -146,7 +146,7 @@ func (wd *workloadDef) Complete(ctx process.Context, abstractTemplate string, pa
func (wd *workloadDef) getTemplateContext(ctx process.Context, cli client.Reader, ns string) (map[string]interface{}, error) {
var root = initRoot(ctx.BaseContextLabels())
var commonLabels = getCommonLabels(ctx.BaseContextLabels())
var commonLabels = GetCommonLabels(ctx.BaseContextLabels())
base, assists := ctx.Output()
componentWorkload, err := base.Unstructured()
@@ -334,7 +334,8 @@ func (td *traitDef) Complete(ctx process.Context, abstractTemplate string, param
return nil
}
func getCommonLabels(contextLabels map[string]string) map[string]string {
// GetCommonLabels will convert context based labels to OAM standard labels
func GetCommonLabels(contextLabels map[string]string) map[string]string {
var commonLabels = map[string]string{}
for k, v := range contextLabels {
switch k {
@@ -343,7 +344,7 @@ func getCommonLabels(contextLabels map[string]string) map[string]string {
case process.ContextName:
commonLabels[oam.LabelAppComponent] = v
case process.ContextAppRevision:
// TODO(wonderflow): do we need to add appRevision into common labels ? Actually it's appConfig name in our current design.
commonLabels[oam.LabelAppRevision] = v
}
}
return commonLabels
@@ -359,7 +360,7 @@ func initRoot(contextLabels map[string]string) map[string]interface{} {
func (td *traitDef) getTemplateContext(ctx process.Context, cli client.Reader, ns string) (map[string]interface{}, error) {
var root = initRoot(ctx.BaseContextLabels())
var commonLabels = getCommonLabels(ctx.BaseContextLabels())
var commonLabels = GetCommonLabels(ctx.BaseContextLabels())
_, assists := ctx.Output()
outputs := make(map[string]interface{})
+1 -1
View File
@@ -48,11 +48,11 @@ const (
type Context interface {
SetBase(base model.Instance)
AppendAuxiliaries(auxiliaries ...Auxiliary)
SetConfigs(configs []map[string]string)
Output() (model.Instance, []Auxiliary)
BaseContextFile() string
ExtendedContextFile() string
BaseContextLabels() map[string]string
SetConfigs(configs []map[string]string)
InsertSecrets(outputSecretName string, requiredSecrets []RequiredSecrets)
}