github.com/oam-dev/kubevela@v1.9.11/test/e2e-test/definition_revision_test.go (about)

     1  /*
     2   Copyright 2021. The KubeVela Authors.
     3  
     4   Licensed under the Apache License, Version 2.0 (the "License");
     5   you may not use this file except in compliance with the License.
     6   You may obtain a copy of the License at
     7  
     8       http://www.apache.org/licenses/LICENSE-2.0
     9  
    10   Unless required by applicable law or agreed to in writing, software
    11   distributed under the License is distributed on an "AS IS" BASIS,
    12   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   See the License for the specific language governing permissions and
    14   limitations under the License.
    15  */
    16  
    17  package controllers_test
    18  
    19  import (
    20  	"context"
    21  	"fmt"
    22  	"time"
    23  
    24  	. "github.com/onsi/ginkgo/v2"
    25  	. "github.com/onsi/gomega"
    26  	"github.com/pkg/errors"
    27  	appsv1 "k8s.io/api/apps/v1"
    28  	batchv1 "k8s.io/api/batch/v1"
    29  	corev1 "k8s.io/api/core/v1"
    30  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    31  	"sigs.k8s.io/controller-runtime/pkg/client"
    32  
    33  	"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
    34  	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
    35  	"github.com/oam-dev/kubevela/pkg/oam"
    36  	"github.com/oam-dev/kubevela/pkg/oam/util"
    37  )
    38  
    39  var _ = Describe("Test application of the specified definition version", func() {
    40  	ctx := context.Background()
    41  
    42  	var namespace string
    43  	var ns corev1.Namespace
    44  
    45  	BeforeEach(func() {
    46  		namespace = randomNamespaceName("defrev-e2e-test")
    47  		ns = corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}
    48  
    49  		Eventually(func() error {
    50  			return k8sClient.Create(ctx, &ns)
    51  		}, time.Second*3, time.Microsecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{}))
    52  
    53  		labelV1 := labelWithNoTemplate.DeepCopy()
    54  		labelV1.Spec.Schematic.CUE.Template = labelV1Template
    55  		labelV1.SetNamespace(namespace)
    56  		Expect(k8sClient.Create(ctx, labelV1)).Should(Succeed())
    57  
    58  		labelV1DefRev := new(v1beta1.DefinitionRevision)
    59  		Eventually(func() error {
    60  			return k8sClient.Get(ctx, client.ObjectKey{Name: "label-v1", Namespace: namespace}, labelV1DefRev)
    61  		}, 15*time.Second, time.Second).Should(BeNil())
    62  
    63  		labelV2 := new(v1beta1.TraitDefinition)
    64  		Eventually(func() error {
    65  			err := k8sClient.Get(ctx, client.ObjectKey{Name: "label", Namespace: namespace}, labelV2)
    66  			if err != nil {
    67  				return err
    68  			}
    69  			labelV2.Spec.Schematic.CUE.Template = labelV2Template
    70  			return k8sClient.Update(ctx, labelV2)
    71  		}, 15*time.Second, time.Second).Should(BeNil())
    72  
    73  		labelV2DefRev := new(v1beta1.DefinitionRevision)
    74  		Eventually(func() error {
    75  			return k8sClient.Get(ctx, client.ObjectKey{Name: "label-v2", Namespace: namespace}, labelV2DefRev)
    76  		}, 15*time.Second, time.Second).Should(BeNil())
    77  
    78  		webserviceV1 := webServiceWithNoTemplate.DeepCopy()
    79  		webserviceV1.Spec.Schematic.CUE.Template = webServiceV1Template
    80  		webserviceV1.SetNamespace(namespace)
    81  		Expect(k8sClient.Create(ctx, webserviceV1)).Should(Succeed())
    82  
    83  		webserviceV1DefRev := new(v1beta1.DefinitionRevision)
    84  		Eventually(func() error {
    85  			return k8sClient.Get(ctx, client.ObjectKey{Name: "webservice-v1", Namespace: namespace}, webserviceV1DefRev)
    86  		}, 15*time.Second, time.Second).Should(BeNil())
    87  
    88  		webserviceV2 := new(v1beta1.ComponentDefinition)
    89  		Eventually(func() error {
    90  			err := k8sClient.Get(ctx, client.ObjectKey{Name: "webservice", Namespace: namespace}, webserviceV2)
    91  			if err != nil {
    92  				return err
    93  			}
    94  			webserviceV2.Spec.Schematic.CUE.Template = webServiceV2Template
    95  			return k8sClient.Update(ctx, webserviceV2)
    96  		}, 15*time.Second, time.Second).Should(BeNil())
    97  
    98  		webserviceV2DefRev := new(v1beta1.DefinitionRevision)
    99  		Eventually(func() error {
   100  			return k8sClient.Get(ctx, client.ObjectKey{Name: "webservice-v2", Namespace: namespace}, webserviceV2DefRev)
   101  		}, 15*time.Second, time.Second).Should(BeNil())
   102  
   103  		jobV1 := jobComponentDef.DeepCopy()
   104  		jobV1.SetNamespace(namespace)
   105  		Expect(k8sClient.Create(ctx, jobV1)).Should(Succeed())
   106  
   107  		jobV1Rev := new(v1beta1.DefinitionRevision)
   108  		Eventually(func() error {
   109  			return k8sClient.Get(ctx, client.ObjectKey{Name: "job-v1.2.1", Namespace: namespace}, jobV1Rev)
   110  		}, 15*time.Second, time.Second).Should(BeNil())
   111  	})
   112  
   113  	AfterEach(func() {
   114  		By("Clean up resources after a test")
   115  		k8sClient.DeleteAllOf(ctx, &v1beta1.Application{}, client.InNamespace(namespace))
   116  		k8sClient.DeleteAllOf(ctx, &v1beta1.ComponentDefinition{}, client.InNamespace(namespace))
   117  		k8sClient.DeleteAllOf(ctx, &v1beta1.WorkloadDefinition{}, client.InNamespace(namespace))
   118  		k8sClient.DeleteAllOf(ctx, &v1beta1.TraitDefinition{}, client.InNamespace(namespace))
   119  		k8sClient.DeleteAllOf(ctx, &v1beta1.DefinitionRevision{}, client.InNamespace(namespace))
   120  
   121  		By(fmt.Sprintf("Delete the entire namespaceName %s", ns.Name))
   122  		Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(Succeed())
   123  	})
   124  
   125  	It("Test deploy application which containing cue rendering module", func() {
   126  		var (
   127  			appName   = "test-website-app"
   128  			comp1Name = "front"
   129  			comp2Name = "backend"
   130  		)
   131  
   132  		workerV1 := workerWithNoTemplate.DeepCopy()
   133  		workerV1.Spec.Workload = common.WorkloadTypeDescriptor{
   134  			Definition: common.WorkloadGVK{
   135  				APIVersion: "batch/v1",
   136  				Kind:       "Job",
   137  			},
   138  		}
   139  		workerV1.Spec.Schematic.CUE.Template = workerV1Template
   140  		workerV1.SetNamespace(namespace)
   141  		Expect(k8sClient.Create(ctx, workerV1)).Should(Succeed())
   142  
   143  		workerV1DefRev := new(v1beta1.DefinitionRevision)
   144  		Eventually(func() error {
   145  			return k8sClient.Get(ctx, client.ObjectKey{Name: "worker-v1", Namespace: namespace}, workerV1DefRev)
   146  		}, 15*time.Second, time.Second).Should(BeNil())
   147  
   148  		workerV2 := new(v1beta1.ComponentDefinition)
   149  		Eventually(func() error {
   150  			err := k8sClient.Get(ctx, client.ObjectKey{Name: "worker", Namespace: namespace}, workerV2)
   151  			if err != nil {
   152  				return err
   153  			}
   154  			workerV1.Spec.Workload = common.WorkloadTypeDescriptor{
   155  				Definition: common.WorkloadGVK{
   156  					APIVersion: "apps/v1",
   157  					Kind:       "Deployment",
   158  				},
   159  			}
   160  			workerV2.Spec.Schematic.CUE.Template = workerV2Template
   161  			return k8sClient.Update(ctx, workerV2)
   162  		}, 15*time.Second, time.Second).Should(BeNil())
   163  
   164  		workerV2DefRev := new(v1beta1.DefinitionRevision)
   165  		Eventually(func() error {
   166  			return k8sClient.Get(ctx, client.ObjectKey{Name: "worker-v2", Namespace: namespace}, workerV2DefRev)
   167  		}, 15*time.Second, time.Second).Should(BeNil())
   168  
   169  		app := v1beta1.Application{
   170  			ObjectMeta: metav1.ObjectMeta{
   171  				Name:      appName,
   172  				Namespace: namespace,
   173  			},
   174  			Spec: v1beta1.ApplicationSpec{
   175  				Components: []common.ApplicationComponent{
   176  					{
   177  						Name: comp1Name,
   178  						Type: "webservice",
   179  						Properties: util.Object2RawExtension(map[string]interface{}{
   180  							"image": "nginx",
   181  						}),
   182  						Traits: []common.ApplicationTrait{
   183  							{
   184  								Type: "label",
   185  								Properties: util.Object2RawExtension(map[string]interface{}{
   186  									"labels": map[string]string{
   187  										"hello": "world",
   188  									},
   189  								}),
   190  							},
   191  						},
   192  					},
   193  					{
   194  						Name: comp2Name,
   195  						Type: "worker",
   196  						Properties: util.Object2RawExtension(map[string]interface{}{
   197  							"image": "busybox",
   198  							"cmd":   []string{"sleep", "1000"},
   199  						}),
   200  					},
   201  				},
   202  			},
   203  		}
   204  
   205  		By("Create application")
   206  		Eventually(func() error {
   207  			return k8sClient.Create(ctx, app.DeepCopy())
   208  		}, 10*time.Second, 500*time.Millisecond).Should(Succeed())
   209  
   210  		By("Verify the workload(deployment) is created successfully")
   211  		webServiceDeploy := &appsv1.Deployment{}
   212  		deployName := comp1Name
   213  		Eventually(func() error {
   214  			return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, webServiceDeploy)
   215  		}, 30*time.Second, 3*time.Second).Should(Succeed())
   216  
   217  		workerDeploy := &appsv1.Deployment{}
   218  		deployName = comp2Name
   219  		Eventually(func() error {
   220  			return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, workerDeploy)
   221  		}, 30*time.Second, 3*time.Second).Should(Succeed())
   222  
   223  		By("Verify trait is applied to the workload")
   224  		webserviceLabels := webServiceDeploy.GetLabels()
   225  		Expect(webserviceLabels["hello"]).Should(Equal("world"))
   226  
   227  		By("Update Application and Specify the Definition version in Application")
   228  		app = v1beta1.Application{
   229  			ObjectMeta: metav1.ObjectMeta{
   230  				Name:      appName,
   231  				Namespace: namespace,
   232  			},
   233  			Spec: v1beta1.ApplicationSpec{
   234  				Components: []common.ApplicationComponent{
   235  					{
   236  						Name: comp1Name,
   237  						Type: "webservice@v1",
   238  						Properties: util.Object2RawExtension(map[string]interface{}{
   239  							"image": "nginx",
   240  						}),
   241  						Traits: []common.ApplicationTrait{
   242  							{
   243  								Type: "label@v1",
   244  								Properties: util.Object2RawExtension(map[string]interface{}{
   245  									"labels": map[string]string{
   246  										"hello": "kubevela",
   247  									},
   248  								}),
   249  							},
   250  						},
   251  					},
   252  					{
   253  						Name: comp2Name,
   254  						Type: "worker@v1",
   255  						Properties: util.Object2RawExtension(map[string]interface{}{
   256  							"image": "busybox",
   257  							"cmd":   []string{"sleep", "1000"},
   258  						}),
   259  					},
   260  				},
   261  			},
   262  		}
   263  		Expect(k8sClient.Patch(ctx, &app, client.Merge)).Should(Succeed())
   264  
   265  		By("Wait for dispatching v2 resources successfully")
   266  		Eventually(func() error {
   267  			RequestReconcileNow(ctx, &app)
   268  			rt := &v1beta1.ResourceTracker{}
   269  			if err := k8sClient.Get(ctx, client.ObjectKey{Name: fmt.Sprintf("%s-v2-%s", appName, namespace)}, rt); err != nil {
   270  				return err
   271  			}
   272  			if len(rt.Spec.ManagedResources) != 0 {
   273  				return nil
   274  			}
   275  			return errors.New("v2 resources have not been dispatched")
   276  		}, 10*time.Second, 500*time.Millisecond).Should(Succeed())
   277  
   278  		By("Verify the workload(deployment) is created successfully")
   279  		webServiceV1Deploy := &appsv1.Deployment{}
   280  		deployName = comp1Name
   281  		Eventually(func() error {
   282  			return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, webServiceV1Deploy)
   283  		}, 30*time.Second, 3*time.Second).Should(Succeed())
   284  
   285  		By("Verify the workload(job) is created successfully")
   286  		workerJob := &batchv1.Job{}
   287  		jobName := comp2Name
   288  		Eventually(func() error {
   289  			return k8sClient.Get(ctx, client.ObjectKey{Name: jobName, Namespace: namespace}, workerJob)
   290  		}, 30*time.Second, 3*time.Second).Should(Succeed())
   291  
   292  		By("Verify trait is applied to the workload")
   293  		webserviceV1Labels := webServiceV1Deploy.GetLabels()
   294  		Expect(webserviceV1Labels["hello"]).Should(Equal("kubevela"))
   295  
   296  		By("Check Application is rendered by the specified version of the Definition")
   297  		Expect(webServiceV1Deploy.Labels["componentdefinition.oam.dev/version"]).Should(Equal("v1"))
   298  		Expect(webServiceV1Deploy.Labels["traitdefinition.oam.dev/version"]).Should(Equal("v1"))
   299  
   300  		By("Application specifies the wrong version of the Definition, it will raise an error")
   301  		app = v1beta1.Application{
   302  			ObjectMeta: metav1.ObjectMeta{
   303  				Name:      appName,
   304  				Namespace: namespace,
   305  			},
   306  			Spec: v1beta1.ApplicationSpec{
   307  				Components: []common.ApplicationComponent{
   308  					{
   309  						Name: comp1Name,
   310  						Type: "webservice@v10",
   311  						Properties: util.Object2RawExtension(map[string]interface{}{
   312  							"image": "nginx",
   313  							"cmd":   []string{"sleep", "1000"},
   314  						}),
   315  					},
   316  				},
   317  			},
   318  		}
   319  		Expect(k8sClient.Patch(ctx, &app, client.Merge)).Should(HaveOccurred())
   320  	})
   321  
   322  	It("Test deploy application which specify the name of component", func() {
   323  		compName := "job"
   324  		app := v1beta1.Application{
   325  			ObjectMeta: metav1.ObjectMeta{
   326  				Name:      "test-defrevision-app-with-job",
   327  				Namespace: namespace,
   328  			},
   329  			Spec: v1beta1.ApplicationSpec{
   330  				Components: []common.ApplicationComponent{
   331  					{
   332  						Name: compName,
   333  						Type: "job@v1.2.1",
   334  						Properties: util.Object2RawExtension(map[string]interface{}{
   335  							"image": "busybox",
   336  							"cmd":   []string{"sleep", "1000"},
   337  						}),
   338  					},
   339  				},
   340  			},
   341  		}
   342  		Expect(k8sClient.Create(ctx, &app)).Should(Succeed())
   343  
   344  		By("Verify the workload(job) is created successfully")
   345  		busyBoxJob := &batchv1.Job{}
   346  		jobName := compName
   347  		Eventually(func() error {
   348  			return k8sClient.Get(ctx, client.ObjectKey{Name: jobName, Namespace: namespace}, busyBoxJob)
   349  		}, 30*time.Second, 3*time.Second).Should(Succeed())
   350  	})
   351  
   352  	// refer to https://github.com/oam-dev/kubevela/discussions/1810#discussioncomment-914295
   353  	It("Test k8s resources created by application whether with correct label", func() {
   354  		var (
   355  			appName  = "test-resources-labels"
   356  			compName = "web"
   357  		)
   358  
   359  		exposeV1 := exposeWithNoTemplate.DeepCopy()
   360  		exposeV1.Spec.Schematic.CUE.Template = exposeV1Template
   361  		exposeV1.SetNamespace(namespace)
   362  		Expect(k8sClient.Create(ctx, exposeV1)).Should(Succeed())
   363  
   364  		exposeV1DefRev := new(v1beta1.DefinitionRevision)
   365  		Eventually(func() error {
   366  			return k8sClient.Get(ctx, client.ObjectKey{Name: "expose-v1", Namespace: namespace}, exposeV1DefRev)
   367  		}, 15*time.Second, time.Second).Should(BeNil())
   368  
   369  		exposeV2 := new(v1beta1.TraitDefinition)
   370  		Eventually(func() error {
   371  			err := k8sClient.Get(ctx, client.ObjectKey{Name: "expose", Namespace: namespace}, exposeV2)
   372  			if err != nil {
   373  				return err
   374  			}
   375  			exposeV2.Spec.Schematic.CUE.Template = exposeV2Template
   376  			return k8sClient.Update(ctx, exposeV2)
   377  		}, 15*time.Second, time.Second).Should(BeNil())
   378  
   379  		exposeV2DefRev := new(v1beta1.DefinitionRevision)
   380  		Eventually(func() error {
   381  			return k8sClient.Get(ctx, client.ObjectKey{Name: "expose-v2", Namespace: namespace}, exposeV2DefRev)
   382  		}, 15*time.Second, time.Second).Should(BeNil())
   383  
   384  		app := v1beta1.Application{
   385  			ObjectMeta: metav1.ObjectMeta{
   386  				Name:      appName,
   387  				Namespace: namespace,
   388  			},
   389  			Spec: v1beta1.ApplicationSpec{
   390  				Components: []common.ApplicationComponent{
   391  					{
   392  						Name: compName,
   393  						Type: "webservice@v1",
   394  						Properties: util.Object2RawExtension(map[string]interface{}{
   395  							"image": "crccheck/hello-world",
   396  							"port":  8000,
   397  						}),
   398  						Traits: []common.ApplicationTrait{
   399  							{
   400  								Type: "expose@v1",
   401  								Properties: util.Object2RawExtension(map[string]interface{}{
   402  									"port": []int{8000},
   403  								}),
   404  							},
   405  						},
   406  					},
   407  				},
   408  			},
   409  		}
   410  
   411  		By("Create application")
   412  		Eventually(func() error {
   413  			return k8sClient.Create(ctx, app.DeepCopy())
   414  		}, 10*time.Second, 500*time.Millisecond).Should(Succeed())
   415  
   416  		By("Verify the workload(deployment) is created successfully")
   417  		webServiceDeploy := &appsv1.Deployment{}
   418  		deployName := compName
   419  		Eventually(func() error {
   420  			return k8sClient.Get(ctx, client.ObjectKey{Name: deployName, Namespace: namespace}, webServiceDeploy)
   421  		}, 30*time.Second, 3*time.Second).Should(Succeed())
   422  
   423  		By("Verify the workload label generated by KubeVela")
   424  		workloadLabel := webServiceDeploy.GetLabels()[oam.WorkloadTypeLabel]
   425  		Expect(workloadLabel).Should(Equal("webservice-v1"))
   426  
   427  		By("Verify the traPIt(service) is created successfully")
   428  		exposeSVC := &corev1.Service{}
   429  		Eventually(func() error {
   430  			return k8sClient.Get(ctx, client.ObjectKey{Name: compName, Namespace: namespace}, exposeSVC)
   431  		}, 30*time.Second, 3*time.Second).Should(Succeed())
   432  
   433  		By("Verify the trait label generated by KubeVela")
   434  		traitLabel := exposeSVC.GetLabels()[oam.TraitTypeLabel]
   435  		Expect(traitLabel).Should(Equal("expose-v1"))
   436  	})
   437  })
   438  
   439  var webServiceWithNoTemplate = &v1beta1.ComponentDefinition{
   440  	TypeMeta: metav1.TypeMeta{
   441  		Kind:       "ComponentDefinition",
   442  		APIVersion: "core.oam.dev/v1beta1",
   443  	},
   444  	ObjectMeta: metav1.ObjectMeta{
   445  		Name: "webservice",
   446  	},
   447  	Spec: v1beta1.ComponentDefinitionSpec{
   448  		Workload: common.WorkloadTypeDescriptor{
   449  			Definition: common.WorkloadGVK{
   450  				APIVersion: "apps/v1",
   451  				Kind:       "Deployment",
   452  			},
   453  		},
   454  		Schematic: &common.Schematic{
   455  			CUE: &common.CUE{
   456  				Template: "",
   457  			},
   458  		},
   459  	},
   460  }
   461  
   462  var workerWithNoTemplate = &v1beta1.ComponentDefinition{
   463  	TypeMeta: metav1.TypeMeta{
   464  		Kind:       "ComponentDefinition",
   465  		APIVersion: "core.oam.dev/v1beta1",
   466  	},
   467  	ObjectMeta: metav1.ObjectMeta{
   468  		Name: "worker",
   469  	},
   470  	Spec: v1beta1.ComponentDefinitionSpec{
   471  		Schematic: &common.Schematic{
   472  			CUE: &common.CUE{
   473  				Template: "",
   474  			},
   475  		},
   476  	},
   477  }
   478  
   479  var jobComponentDef = &v1beta1.ComponentDefinition{
   480  	TypeMeta: metav1.TypeMeta{
   481  		Kind:       "ComponentDefinition",
   482  		APIVersion: "core.oam.dev/v1beta1",
   483  	},
   484  	ObjectMeta: metav1.ObjectMeta{
   485  		Name: "job",
   486  		Annotations: map[string]string{
   487  			oam.AnnotationDefinitionRevisionName: "1.2.1",
   488  		},
   489  	},
   490  	Spec: v1beta1.ComponentDefinitionSpec{
   491  		Workload: common.WorkloadTypeDescriptor{
   492  			Definition: common.WorkloadGVK{
   493  				APIVersion: "batch/v1",
   494  				Kind:       "Job",
   495  			},
   496  		},
   497  		Schematic: &common.Schematic{
   498  			CUE: &common.CUE{
   499  				Template: workerV1Template,
   500  			},
   501  		},
   502  	},
   503  }
   504  
   505  var KUBEWorker = &v1beta1.ComponentDefinition{
   506  	TypeMeta: metav1.TypeMeta{
   507  		Kind:       "ComponentDefinition",
   508  		APIVersion: "core.oam.dev/v1beta1",
   509  	},
   510  	ObjectMeta: metav1.ObjectMeta{
   511  		Name: "kube-worker",
   512  	},
   513  }
   514  
   515  var HELMWorker = &v1beta1.ComponentDefinition{
   516  	TypeMeta: metav1.TypeMeta{
   517  		Kind:       "ComponentDefinition",
   518  		APIVersion: "core.oam.dev/v1beta1",
   519  	},
   520  	ObjectMeta: metav1.ObjectMeta{
   521  		Name: "helm-worker",
   522  	},
   523  }
   524  
   525  var labelWithNoTemplate = &v1beta1.TraitDefinition{
   526  	TypeMeta: metav1.TypeMeta{
   527  		Kind:       "TraitDefinition",
   528  		APIVersion: "core.oam.dev/v1beta1",
   529  	},
   530  	ObjectMeta: metav1.ObjectMeta{
   531  		Name: "label",
   532  	},
   533  	Spec: v1beta1.TraitDefinitionSpec{
   534  		Schematic: &common.Schematic{
   535  			CUE: &common.CUE{
   536  				Template: "",
   537  			},
   538  		},
   539  	},
   540  }
   541  
   542  var exposeWithNoTemplate = &v1beta1.TraitDefinition{
   543  	TypeMeta: metav1.TypeMeta{
   544  		Kind:       "TraitDefinition",
   545  		APIVersion: "core.oam.dev/v1beta1",
   546  	},
   547  	ObjectMeta: metav1.ObjectMeta{
   548  		Name: "expose",
   549  	},
   550  	Spec: v1beta1.TraitDefinitionSpec{
   551  		Schematic: &common.Schematic{
   552  			CUE: &common.CUE{
   553  				Template: "",
   554  			},
   555  		},
   556  	},
   557  }
   558  
   559  var webServiceV1Template = `output: {
   560  	apiVersion: "apps/v1"
   561  	kind:       "Deployment"
   562  	metadata: labels: {
   563  		"componentdefinition.oam.dev/version": "v1"
   564  	}
   565  	spec: {
   566  		selector: matchLabels: {
   567  			"app.oam.dev/component": context.name
   568  		}
   569  		template: {
   570  			metadata: labels: {
   571  				"app.oam.dev/component": context.name
   572  			}
   573  			spec: {
   574  				containers: [{
   575  					name:  context.name
   576  					image: parameter.image
   577  					if parameter["cmd"] != _|_ {
   578  						command: parameter.cmd
   579  					}
   580  					if parameter["env"] != _|_ {
   581  						env: parameter.env
   582  					}
   583  					if context["config"] != _|_ {
   584  						env: context.config
   585  					}
   586  					ports: [{
   587  						containerPort: parameter.port
   588  					}]
   589  					if parameter["cpu"] != _|_ {
   590  						resources: {
   591  							limits:
   592  								cpu: parameter.cpu
   593  							requests:
   594  								cpu: parameter.cpu
   595  						}
   596  					}
   597  				}]
   598  		}
   599  		}
   600  	}
   601  }
   602  parameter: {
   603  	image: string
   604  	cmd?: [...string]
   605  	port: *80 | int
   606  	env?: [...{
   607  		name:   string
   608  		value?: string
   609  		valueFrom?: {
   610  			secretKeyRef: {
   611  				name: string
   612  				key:  string
   613  			}
   614  		}
   615  	}]
   616  	cpu?: string
   617  }
   618  `
   619  
   620  var webServiceV2Template = `output: {
   621      apiVersion: "apps/v1"
   622      kind:       "Deployment"
   623      spec: {
   624          selector: matchLabels: {
   625              "app.oam.dev/component": context.name
   626          }
   627          template: {
   628              metadata: labels: {
   629                  "app.oam.dev/component": context.name
   630                  if parameter.addRevisionLabel {
   631                      "app.oam.dev/appRevision": context.appRevision
   632                 	 }
   633              }
   634              spec: {
   635                  containers: [{
   636                      name:  context.name
   637                      image: parameter.image
   638                      if parameter["cmd"] != _|_ {
   639                          command: parameter.cmd
   640                      }
   641                      if parameter["env"] != _|_ {
   642                          env: parameter.env
   643                      }
   644                      if context["config"] != _|_ {
   645                          env: context.config
   646                      }
   647                      ports: [{
   648                          containerPort: parameter.port
   649                      }]
   650                      if parameter["cpu"] != _|_ {
   651                          resources: {
   652                              limits:
   653                                  cpu: parameter.cpu
   654                              requests:
   655                                  cpu: parameter.cpu
   656                          }
   657                      }
   658                  }]
   659          }
   660          }
   661      }
   662  }
   663  parameter: {
   664      image: string
   665      cmd?: [...string]
   666      port: *80 | int
   667      env?: [...{
   668          name: string
   669          value?: string
   670          valueFrom?: {
   671              secretKeyRef: {
   672                  name: string
   673                  key: string
   674              }
   675          }
   676      }]
   677      cpu?: string
   678      addRevisionLabel: *false | bool
   679  }
   680  `
   681  
   682  var workerV1Template = `output: {
   683  	apiVersion: "batch/v1"
   684  	kind:       "Job"
   685  	spec: {
   686  		parallelism: parameter.count
   687  		completions: parameter.count
   688  		template: spec: {
   689  			restartPolicy	: parameter.restart
   690  				containers: [{
   691  				name:  context.name
   692  				image: parameter.image
   693  				if parameter["cmd"] != _|_ {
   694  					command: parameter.cmd
   695  				}
   696  			}]
   697  		}
   698  	}
   699  }
   700  parameter: {
   701  	count: *1 | int
   702  	image: string
   703  	restart: *"Never" | string
   704  	cmd?: [...string]
   705  }
   706  `
   707  
   708  var workerV2Template = `output: {
   709      apiVersion: "apps/v1"
   710      kind:       "Deployment"
   711      spec: {
   712          selector: matchLabels: {
   713              "app.oam.dev/component": context.name
   714          }
   715          template: {
   716              metadata: labels: {
   717                  "app.oam.dev/component": context.name
   718              }
   719              spec: {
   720                  containers: [{
   721                      name:  context.name
   722                      image: parameter.image
   723  
   724                      if parameter["cmd"] != _|_ {
   725                          command: parameter.cmd
   726                      }
   727                  }]
   728              }
   729          }
   730      }
   731  }
   732  parameter: {
   733      image: string
   734      cmd?: [...string]
   735  }
   736  `
   737  
   738  var labelV1Template = `patch: {
   739  	metadata: labels: {
   740  		for k, v in parameter.labels {
   741  			"\(k)": v
   742  		}
   743  		"traitdefinition.oam.dev/version": "v1"
   744  	}
   745  }
   746  parameter: {
   747  	labels: [string]: string
   748  }
   749  `
   750  
   751  var labelV2Template = `patch: {
   752  	metadata: labels: {
   753  		for k, v in parameter.labels {
   754  			"\(k)": v
   755  		}	
   756  	}
   757  }
   758  parameter: {
   759  	labels: [string]: string
   760  }
   761  `
   762  
   763  var KUBEWorkerV1Template = `apiVersion: apps/v1
   764  kind: Deployment
   765  spec:
   766    selector:
   767      matchLabels:
   768        app: nginx
   769    template:
   770      metadata:
   771        labels:
   772          app: nginx
   773      spec:
   774        containers:
   775        - name: nginx
   776        ports:
   777        - containerPort: 80
   778  `
   779  
   780  var KUBEWorkerV2Template = `apiVersion: "batch/v1"
   781  kind: "Job"
   782  spec:
   783    parallelism: 1
   784    completions: 1
   785    template:
   786      spec:
   787        restartPolicy: "Never"
   788        containers:
   789        - name: "job"
   790          image: "busybox"
   791          command:
   792          - "sleep"
   793          - "1000"
   794  `
   795  
   796  var exposeV1Template = `
   797  outputs: service: {
   798  	apiVersion: "v1"
   799  	kind:       "Service"
   800  	metadata:
   801  		name: context.name
   802  	spec: {
   803  		selector:
   804  			"app.oam.dev/component": context.name
   805  		ports: [
   806  			for p in parameter.port {
   807  				port:       p
   808  				targetPort: p
   809  			},
   810  		]
   811  	}
   812  }
   813  parameter: {
   814  	// +usage=Specify the exposion ports
   815  	port: [...int]
   816  }
   817  `
   818  
   819  var exposeV2Template = `
   820  outputs: service: {
   821  	apiVersion: "v1"
   822  	kind:       "Service"
   823  	metadata:
   824  		name: context.name
   825  	spec: {
   826  		selector: {
   827  			"app.oam.dev/component": context.name
   828  		}
   829  		ports: [
   830  			for k, v in parameter.http {
   831  				port:       v
   832  				targetPort: v
   833  			},
   834  		]
   835  	}
   836  }
   837  
   838  outputs: ingress: {
   839  	apiVersion: "networking.k8s.io/v1beta1"
   840  	kind:       "Ingress"
   841  	metadata:
   842  		name: context.name
   843  	spec: {
   844  		rules: [{
   845  			host: parameter.domain
   846  			http: {
   847  				paths: [
   848  					for k, v in parameter.http {
   849  						path: k
   850  						backend: {
   851  							serviceName: context.name
   852  							servicePort: v
   853  						}
   854  					},
   855  				]
   856  			}
   857  		}]
   858  	}
   859  }
   860  
   861  parameter: {
   862  	domain: string
   863  	http: [string]: int
   864  }
   865  `