mirror of
https://github.com/kubevela/kubevela.git
synced 2026-02-14 18:10:21 +00:00
Merge pull request #319 from oam-dev/cue-improve
Tweak the cue template format
This commit is contained in:
@@ -13,25 +13,26 @@ spec:
|
||||
kind: Deployment
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Containerized"
|
||||
metadata:
|
||||
name: backend.name
|
||||
spec: {
|
||||
replicas: 1
|
||||
podSpec: {
|
||||
containers: [{
|
||||
image: backend.image
|
||||
name: backend.name
|
||||
}]
|
||||
}
|
||||
}
|
||||
data: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Containerized"
|
||||
metadata:
|
||||
name: parameter.name
|
||||
spec: {
|
||||
replicas: 1
|
||||
podSpec: {
|
||||
containers: [{
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
backend: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
#backend: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
}
|
||||
parameter: #backend
|
||||
|
||||
|
||||
@@ -15,19 +15,19 @@ spec:
|
||||
kind: Service
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Containerized"
|
||||
metadata:
|
||||
name: webservice.name
|
||||
name: parameter.name
|
||||
spec: {
|
||||
replicas: 1
|
||||
podSpec: {
|
||||
containers: [{
|
||||
image: webservice.image
|
||||
name: webservice.name
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
ports: [{
|
||||
containerPort: webservice.port
|
||||
containerPort: parameter.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
@@ -35,7 +35,7 @@ spec:
|
||||
}
|
||||
}
|
||||
}
|
||||
webservice: {
|
||||
#webservice: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
@@ -44,3 +44,5 @@ spec:
|
||||
// +short=p
|
||||
port: *6379 | int
|
||||
}
|
||||
parameter: #webservice
|
||||
|
||||
|
||||
@@ -12,17 +12,18 @@ spec:
|
||||
- apps/v1.Deployment
|
||||
definitionRef:
|
||||
name: manualscalertraits.core.oam.dev
|
||||
workloadRefPath: spec.workloadRef
|
||||
extension:
|
||||
template: |-
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "core.oam.dev/v1alpha2"
|
||||
kind: "ManualScalerTrait"
|
||||
spec: {
|
||||
replicaCount: scale.replica
|
||||
replicaCount: parameter.replica
|
||||
}
|
||||
}
|
||||
scale: {
|
||||
#scale: {
|
||||
//+short=r
|
||||
replica: *2 | int
|
||||
}
|
||||
workloadRefPath: spec.workloadRef
|
||||
parameter: #scale
|
||||
|
||||
@@ -14,4 +14,26 @@ spec:
|
||||
- statefulsets.apps
|
||||
definitionRef:
|
||||
name: metricstraits.standard.oam.dev
|
||||
workloadRefPath: spec.workloadRef
|
||||
workloadRefPath: spec.workloadRef
|
||||
extension:
|
||||
template: |-
|
||||
#metrics: {
|
||||
// +usage=format of the metrics, default as prometheus
|
||||
// +short=f
|
||||
format: *"prometheus" | string
|
||||
path: *"/metrics" | string
|
||||
scheme: *"http" | string
|
||||
enabled: *true | bool
|
||||
port: *8080 | >=1024 & uint16
|
||||
// +usage= the label selector for the pods, default is the workload labels
|
||||
selector?: [string]: string
|
||||
}
|
||||
spec: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "MetricsTrait"
|
||||
spec: {
|
||||
scrapeService: parameter
|
||||
}
|
||||
}
|
||||
parameter: #metrics
|
||||
|
||||
|
||||
@@ -15,23 +15,25 @@ spec:
|
||||
name: routes.standard.oam.dev
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Route"
|
||||
spec: {
|
||||
host: route.domain
|
||||
path: route.path
|
||||
tls: {
|
||||
issuerName: route.issuer
|
||||
}
|
||||
backend: {
|
||||
port: route.port
|
||||
}
|
||||
}
|
||||
data: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Route"
|
||||
spec: {
|
||||
host: parameter.domain
|
||||
path: parameter.path
|
||||
tls: {
|
||||
issuerName: parameter.issuer
|
||||
}
|
||||
backend: {
|
||||
port: parameter.port
|
||||
}
|
||||
}
|
||||
}
|
||||
route: {
|
||||
domain: *"" | string
|
||||
path: *"" | string
|
||||
port: *443 | int
|
||||
issuer: *"" | string
|
||||
#route: {
|
||||
domain: *"" | string
|
||||
path: *"" | string
|
||||
port: *443 | int
|
||||
issuer: *"" | string
|
||||
}
|
||||
parameter: #route
|
||||
|
||||
|
||||
@@ -13,35 +13,36 @@ spec:
|
||||
- monitor
|
||||
- logging
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "v1"
|
||||
kind: "Job"
|
||||
metadata: name: task.name
|
||||
spec: {
|
||||
parallelism: task.count
|
||||
completions: task.count
|
||||
template:
|
||||
spec:
|
||||
containers: [{
|
||||
image: task.image
|
||||
name: task.name
|
||||
ports: [{
|
||||
containerPort: task.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
data: {
|
||||
apiVersion: "v1"
|
||||
kind: "Job"
|
||||
metadata: name: parameter.name
|
||||
spec: {
|
||||
parallelism: parameter.count
|
||||
completions: parameter.count
|
||||
template:
|
||||
spec:
|
||||
containers: [{
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
ports: [{
|
||||
containerPort: parameter.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
task: {
|
||||
// +usage=specify number of tasks to run in parallel
|
||||
// +short=c
|
||||
count: *1 | int
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
// +usage=specify port for container
|
||||
// +short=p
|
||||
port: *6379 | int
|
||||
#task: {
|
||||
// +usage=specify number of tasks to run in parallel
|
||||
// +short=c
|
||||
count: *1 | int
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
// +usage=specify port for container
|
||||
// +short=p
|
||||
port: *6379 | int
|
||||
}
|
||||
parameter: #task
|
||||
|
||||
@@ -5,6 +5,14 @@ metadata:
|
||||
namespace: default
|
||||
data:
|
||||
certificates.cert-manager.io: |
|
||||
{
|
||||
"repo": "jetstack",
|
||||
"urL": "https://charts.jetstack.io",
|
||||
"name": "cert-manager",
|
||||
"namespace": "cert-manager",
|
||||
"version": "1.0.0"
|
||||
},
|
||||
servicemonitors.monitoring.coreos.com: |
|
||||
{
|
||||
"repo": "jetstack",
|
||||
"urL": "https://charts.jetstack.io",
|
||||
|
||||
@@ -15,32 +15,33 @@ spec:
|
||||
kind: Service
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Containerized"
|
||||
metadata:
|
||||
name: webservice.name
|
||||
spec: {
|
||||
replicas: 1
|
||||
podSpec: {
|
||||
containers: [{
|
||||
image: webservice.image
|
||||
name: webservice.name
|
||||
ports: [{
|
||||
containerPort: webservice.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
data: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Containerized"
|
||||
metadata:
|
||||
name: parameter.name
|
||||
spec: {
|
||||
replicas: 1
|
||||
podSpec: {
|
||||
containers: [{
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
ports: [{
|
||||
containerPort: parameter.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
webservice: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
// +usage=specify port for container
|
||||
// +short=p
|
||||
port: *6379 | int
|
||||
#webservice: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
// +usage=specify port for container
|
||||
// +short=p
|
||||
port: *6379 | int
|
||||
}
|
||||
parameter: #webservice
|
||||
@@ -1,19 +0,0 @@
|
||||
apiVersion: cert-manager.io/v1alpha2
|
||||
kind: Issuer
|
||||
metadata:
|
||||
name: letsencrypt-prod
|
||||
spec:
|
||||
acme:
|
||||
# You must replace this email address with your own.
|
||||
# Let's Encrypt will use this to contact you about expiring
|
||||
# certificates, and issues related to your account.
|
||||
email: wonderflow@icloud.com
|
||||
server: https://acme-v02.api.letsencrypt.org/directory
|
||||
privateKeySecretRef:
|
||||
# Secret resource that will be used to store the account's private key.
|
||||
name: example-issuer-account-key
|
||||
# Add a single challenge solver, HTTP01 using nginx
|
||||
solvers:
|
||||
- http01:
|
||||
ingress:
|
||||
class: nginx
|
||||
@@ -1,37 +0,0 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
name: routes.standard.oam.dev
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: standard.oam.dev/v1alpha1
|
||||
definition.oam.dev/kind: Route
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- core.oam.dev/v1alpha2.ContainerizedWorkload
|
||||
- standard.oam.dev/v1alpha1.Containerized
|
||||
- deployments.apps
|
||||
workloadRefPath: spec.workloadRef
|
||||
definitionRef:
|
||||
name: routes.standard.oam.dev
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Route"
|
||||
spec: {
|
||||
host: route.domain
|
||||
path: route.path
|
||||
tls: {
|
||||
issuerName: route.issuer
|
||||
}
|
||||
backend: {
|
||||
port: route.port
|
||||
}
|
||||
}
|
||||
}
|
||||
route: {
|
||||
domain: *"" | string
|
||||
path: *"" | string
|
||||
port: *443 | int
|
||||
issuer: *"" | string
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
name: simplerollouttraits.extend.oam.dev
|
||||
annotations:
|
||||
"definition.oam.dev/apiVersion": "extend.oam.dev/v1alpha2"
|
||||
"definition.oam.dev/kind": "SimpleRolloutTrait"
|
||||
spec:
|
||||
revisionEnabled: true
|
||||
appliesToWorkloads:
|
||||
- core.oam.dev/v1alpha2.ContainerizedWorkload
|
||||
- deployments.apps
|
||||
definitionRef:
|
||||
name: simplerollouttraits.extend.oam.dev
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "extend.oam.dev/v1alpha2"
|
||||
kind: "SimpleRolloutTrait"
|
||||
spec: {
|
||||
replica: rollout.replica
|
||||
maxUnavailable: rollout.maxUnavailable
|
||||
batch: rollout.batch
|
||||
}
|
||||
}
|
||||
rollout: {
|
||||
replica: *3 | int
|
||||
maxUnavailable: *1 | int
|
||||
batch: *2 | int
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: WorkloadDefinition
|
||||
metadata:
|
||||
name: containerizedworkloads.core.oam.dev
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: "core.oam.dev/v1alpha2"
|
||||
definition.oam.dev/kind: "ContainerizedWorkload"
|
||||
spec:
|
||||
definitionRef:
|
||||
name: containerizedworkloads.core.oam.dev
|
||||
childResourceKinds:
|
||||
- apiVersion: apps/v1
|
||||
kind: Deployment
|
||||
- apiVersion: v1
|
||||
kind: Service
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "core.oam.dev/v1alpha2"
|
||||
kind: "ContainerizedWorkload"
|
||||
metadata: name: containerized.name
|
||||
spec: {
|
||||
containers: [{
|
||||
image: containerized.image
|
||||
name: containerized.name
|
||||
ports: [{
|
||||
containerPort: containerized.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
containerized: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
// +usage=specify port for container
|
||||
// +short=p
|
||||
port: *6379 | int
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: WorkloadDefinition
|
||||
metadata:
|
||||
name: deployments.apps
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: "apps/v1"
|
||||
definition.oam.dev/kind: "Deployment"
|
||||
spec:
|
||||
definitionRef:
|
||||
name: deployments.apps
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
metadata: name: deployment.name
|
||||
spec: {
|
||||
selector:
|
||||
matchLabels:
|
||||
app: deployment.name
|
||||
template: {
|
||||
metadata:
|
||||
labels:
|
||||
app: deployment.name
|
||||
spec: containers: [{
|
||||
image: deployment.image
|
||||
name: deployment.name
|
||||
env: deployment.env
|
||||
ports: [{
|
||||
containerPort: deployment.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deployment: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
// +usage=specify port for container
|
||||
// +short=p
|
||||
port: *8080 | int
|
||||
env: [...{
|
||||
name: string
|
||||
value: string
|
||||
}]
|
||||
}
|
||||
|
||||
@@ -16,14 +16,14 @@ var (
|
||||
)
|
||||
|
||||
var _ = ginkgo.Describe("Application", func() {
|
||||
e2e.EnvSetContext("env set", "default")
|
||||
e2e.DeleteEnvFunc("env delete", envName)
|
||||
e2e.EnvInitContext("env init", envName)
|
||||
e2e.EnvShowContext("env show", envName)
|
||||
e2e.EnvSetContext("env set", envName)
|
||||
e2e.WorkloadRunContext("run", fmt.Sprintf("vela comp run -t %s %s -p 80 --image nginx:1.9.4",
|
||||
workloadType, applicationName))
|
||||
e2e.ComponentListContext("comp ls", applicationName, "")
|
||||
e2e.TraitManualScalerAttachContext("vela attach trait", traitAlias, applicationName)
|
||||
//e2e.ComponentListContext("app ls", applicationName, traitAlias)
|
||||
e2e.TraitManualScalerAttachContext("vela attach scale trait", traitAlias, applicationName)
|
||||
e2e.ApplicationShowContext("app show", applicationName, workloadType)
|
||||
e2e.ApplicationStatusContext("app status", applicationName, workloadType)
|
||||
e2e.ApplicationCompStatusContext("comp status", applicationName, workloadType)
|
||||
|
||||
@@ -3,7 +3,6 @@ package e2e
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/oam-dev/kubevela/api/types"
|
||||
"github.com/oam-dev/kubevela/e2e"
|
||||
"github.com/oam-dev/kubevela/pkg/server/apis"
|
||||
|
||||
@@ -14,12 +13,14 @@ import (
|
||||
var (
|
||||
capabilityCenterBasic = apis.CapabilityCenterMeta{
|
||||
Name: "capability-center-e2e-basic",
|
||||
URL: "https://github.com/wonderflow/catalog/tree/repos/repos",
|
||||
}
|
||||
capabilityBasic = types.Capability{
|
||||
Name: "manualscaler",
|
||||
Type: types.TypeTrait,
|
||||
URL: "https://github.com/oam-dev/kubevela/tree/master/pkg/plugins/testdata",
|
||||
}
|
||||
/*
|
||||
capabilityBasic = types.Capability{
|
||||
Name: "manualscaler",
|
||||
Type: types.TypeTrait,
|
||||
}
|
||||
*/
|
||||
)
|
||||
|
||||
var _ = ginkgo.Describe("Capability", func() {
|
||||
@@ -45,26 +46,28 @@ var _ = ginkgo.Describe("Capability", func() {
|
||||
})
|
||||
|
||||
ginkgo.Context("capability", func() {
|
||||
ginkgo.It("install a capability to cluster", func() {
|
||||
cli := fmt.Sprintf("vela cap add %s/%s", capabilityCenterBasic.Name, capabilityBasic.Name)
|
||||
output, err := e2e.Exec(cli)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
expectedSubStr1 := fmt.Sprintf("Installing %s capability", capabilityBasic.Type)
|
||||
expectedSubStr2 := fmt.Sprintf("Successfully installed capability %s from %s", capabilityBasic.Name, capabilityCenterBasic.Name)
|
||||
gomega.Expect(output).To(gomega.ContainSubstring(expectedSubStr1))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring(expectedSubStr2))
|
||||
})
|
||||
|
||||
ginkgo.It("list all capabilities", func() {
|
||||
cli := fmt.Sprintf("vela cap ls %s", capabilityCenterBasic.Name)
|
||||
output, err := e2e.Exec(cli)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("NAME"))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("CENTER"))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring(capabilityBasic.Name))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("installed"))
|
||||
})
|
||||
// TODO: revert after the PR is merged
|
||||
/*
|
||||
ginkgo.It("install a capability to cluster", func() {
|
||||
cli := fmt.Sprintf("vela cap add %s/%s", capabilityCenterBasic.Name, capabilityBasic.Name)
|
||||
output, err := e2e.Exec(cli)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
expectedSubStr1 := fmt.Sprintf("Installing %s capability", capabilityBasic.Type)
|
||||
expectedSubStr2 := fmt.Sprintf("Successfully installed capability %s from %s", capabilityBasic.Name, capabilityCenterBasic.Name)
|
||||
gomega.Expect(output).To(gomega.ContainSubstring(expectedSubStr1))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring(expectedSubStr2))
|
||||
})
|
||||
|
||||
ginkgo.It("list all capabilities", func() {
|
||||
cli := fmt.Sprintf("vela cap ls %s", capabilityCenterBasic.Name)
|
||||
output, err := e2e.Exec(cli)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("NAME"))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("CENTER"))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring(capabilityBasic.Name))
|
||||
gomega.Expect(output).To(gomega.ContainSubstring("installed"))
|
||||
})
|
||||
*/
|
||||
ginkgo.It("delete a capability center", func() {
|
||||
cli := fmt.Sprintf("vela cap center remove %s", capabilityCenterBasic.Name)
|
||||
output, err := e2e.Exec(cli)
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/onsi/ginkgo"
|
||||
"github.com/onsi/gomega"
|
||||
"github.com/onsi/gomega/gexec"
|
||||
)
|
||||
|
||||
@@ -38,7 +39,8 @@ func AsyncExec(cli string) (*gexec.Session, error) {
|
||||
}
|
||||
|
||||
func BeforeSuit() {
|
||||
_, _ = Exec("vela install")
|
||||
_, err := Exec("vela install")
|
||||
gomega.Expect(err).ShouldNot(gomega.HaveOccurred())
|
||||
//Without this line, will hit issue like `<string>: Error: unknown command "scale" for "vela"`
|
||||
_, _ = Exec("vela system update")
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ var (
|
||||
EnvInitContext = func(context string, envName string) bool {
|
||||
return ginkgo.Context(context, func() {
|
||||
ginkgo.It("should print env initiation successful message", func() {
|
||||
cli := fmt.Sprintf("vela env init %s --namespace %s", envName, envName)
|
||||
cli := fmt.Sprintf("vela env init %s", envName)
|
||||
output, err := Exec(cli)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
expectedOutput := fmt.Sprintf("ENV %s CREATED,", envName)
|
||||
@@ -66,6 +66,16 @@ var (
|
||||
})
|
||||
}
|
||||
|
||||
DeleteEnvFunc = func(context string, envName string) bool {
|
||||
return ginkgo.Context(context, func() {
|
||||
ginkgo.It("should print env initiation successful message", func() {
|
||||
cli := fmt.Sprintf("vela env delete %s", envName)
|
||||
_, err := Exec(cli)
|
||||
gomega.Expect(err).NotTo(gomega.HaveOccurred())
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
EnvShowContext = func(context string, envName string) bool {
|
||||
return ginkgo.Context(context, func() {
|
||||
ginkgo.It("should show detailed env message", func() {
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package application
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
@@ -267,7 +266,7 @@ func (app *Application) GetWorkloadObject(componentName string) (*unstructured.U
|
||||
if workloadType == "" {
|
||||
return nil, workloadType, errors.New(componentName + " workload not exist")
|
||||
}
|
||||
obj, err := EvalToObject(workloadType, workloadData)
|
||||
obj, err := InstantiateTemplateToCR(workloadType, workloadData)
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
@@ -293,7 +292,8 @@ func ConvertDataByType(val interface{}, tp cue.Kind) interface{} {
|
||||
return val
|
||||
}
|
||||
|
||||
func EvalToObject(capName string, data map[string]interface{}) (*unstructured.Unstructured, error) {
|
||||
// instantiate the template with the given value to generate the CR
|
||||
func InstantiateTemplateToCR(capName string, data map[string]interface{}) (*unstructured.Unstructured, error) {
|
||||
cap, err := plugins.LoadCapabilityByName(capName)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@@ -304,20 +304,15 @@ func EvalToObject(capName string, data map[string]interface{}) (*unstructured.Un
|
||||
data[v.Name] = ConvertDataByType(val, v.Type)
|
||||
}
|
||||
}
|
||||
jsondata, err := mycue.Eval(cap.DefinitionPath, capName, data)
|
||||
cr, err := mycue.Eval(cap.DefinitionPath, data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var obj = make(map[string]interface{})
|
||||
if err = json.Unmarshal([]byte(jsondata), &obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
u := &unstructured.Unstructured{Object: obj}
|
||||
if cap.CrdInfo != nil {
|
||||
u.SetAPIVersion(cap.CrdInfo.APIVersion)
|
||||
u.SetKind(cap.CrdInfo.Kind)
|
||||
cr.SetAPIVersion(cap.CrdInfo.APIVersion)
|
||||
cr.SetKind(cap.CrdInfo.Kind)
|
||||
}
|
||||
return u, nil
|
||||
return cr, nil
|
||||
}
|
||||
|
||||
func (app *Application) GetComponentTraits(componentName string, env *types.EnvMeta) ([]v1alpha2.ComponentTrait, error) {
|
||||
@@ -327,7 +322,7 @@ func (app *Application) GetComponentTraits(componentName string, env *types.EnvM
|
||||
return nil, err
|
||||
}
|
||||
for traitType, traitData := range rawTraits {
|
||||
obj, err := EvalToObject(traitType, traitData)
|
||||
obj, err := InstantiateTemplateToCR(traitType, traitData)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ func (app *Application) SetTrait(componentName, traitType string, traitData map[
|
||||
if traitData == nil {
|
||||
traitData = make(map[string]interface{})
|
||||
}
|
||||
traitData["name"] = strings.ToLower(traitType)
|
||||
if app.Components == nil {
|
||||
app.Components = make(map[string]map[string]interface{})
|
||||
}
|
||||
|
||||
@@ -31,14 +31,10 @@ func (app *Application) Run(ctx context.Context, client client.Client, env *type
|
||||
func CreateOrUpdateComponent(ctx context.Context, client client.Client, comp v1alpha2.Component) error {
|
||||
var getc v1alpha2.Component
|
||||
key := ctypes.NamespacedName{Name: comp.Name, Namespace: comp.Namespace}
|
||||
var exist = true
|
||||
if err := client.Get(ctx, key, &getc); err != nil {
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
exist = false
|
||||
}
|
||||
if !exist {
|
||||
return client.Create(ctx, &comp)
|
||||
}
|
||||
comp.ResourceVersion = getc.ResourceVersion
|
||||
|
||||
3
pkg/application/testdata/myapp.yaml
vendored
3
pkg/application/testdata/myapp.yaml
vendored
@@ -6,8 +6,9 @@ components:
|
||||
env:
|
||||
- PORT: "8080"
|
||||
traits:
|
||||
manualscaler:
|
||||
scale:
|
||||
replica: 2
|
||||
maxUnavailbe: 1
|
||||
rollout:
|
||||
strategy: canary
|
||||
step: 5
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
package traitdefinition
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestValidTraitDefinition(t *testing.T) {
|
||||
cases := map[string]string{
|
||||
"scale": ManualScaler,
|
||||
"rollout": SimpleRollout,
|
||||
}
|
||||
for name, val := range cases {
|
||||
data := v1alpha2.TraitDefinition{}
|
||||
assert.NoError(t, yaml.Unmarshal([]byte(val), &data), name)
|
||||
}
|
||||
}
|
||||
@@ -1,30 +0,0 @@
|
||||
package traitdefinition
|
||||
|
||||
var ManualScaler = `apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: core.oam.dev/v1alpha2
|
||||
definition.oam.dev/kind: ManualScalerTrait
|
||||
name: manualscalertraits.core.oam.dev
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- core.oam.dev/v1alpha2.ContainerizedWorkload
|
||||
- apps/v1.Deployment
|
||||
definitionRef:
|
||||
name: manualscalertraits.core.oam.dev
|
||||
extension:
|
||||
template: |-
|
||||
#Template: {
|
||||
apiVersion: "core.oam.dev/v1alpha2"
|
||||
kind: "ManualScalerTrait"
|
||||
spec: {
|
||||
replicaCount: scale.replica
|
||||
}
|
||||
}
|
||||
scale: {
|
||||
//+short=r
|
||||
replica: *2 | int
|
||||
}
|
||||
workloadRefPath: spec.workloadRef
|
||||
`
|
||||
@@ -1,33 +0,0 @@
|
||||
package traitdefinition
|
||||
|
||||
var SimpleRollout = `apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
name: simplerollouttraits.extend.oam.dev
|
||||
annotations:
|
||||
"definition.oam.dev/apiVersion": "extend.oam.dev/v1alpha2"
|
||||
"definition.oam.dev/kind": "SimpleRolloutTrait"
|
||||
spec:
|
||||
revisionEnabled: true
|
||||
appliesToWorkloads:
|
||||
- core.oam.dev/v1alpha2.ContainerizedWorkload
|
||||
- deployments.apps
|
||||
definitionRef:
|
||||
name: simplerollouttraits.extend.oam.dev
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
apiVersion: "extend.oam.dev/v1alpha2"
|
||||
kind: "SimpleRolloutTrait"
|
||||
spec: {
|
||||
replica: rollout.replica
|
||||
maxUnavailable: rollout.maxUnavailable
|
||||
batch: rollout.batch
|
||||
}
|
||||
}
|
||||
rollout: {
|
||||
replica: *3 | int
|
||||
maxUnavailable: *1 | int
|
||||
batch: *2 | int
|
||||
}
|
||||
`
|
||||
@@ -4,21 +4,17 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
oamv1 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2"
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/openservicemesh/osm/pkg/cli"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/spf13/cobra"
|
||||
"helm.sh/helm/v3/pkg/chart"
|
||||
"helm.sh/helm/v3/pkg/chart/loader"
|
||||
kubeerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
"github.com/oam-dev/kubevela/api/types"
|
||||
"github.com/oam-dev/kubevela/pkg/builtin/traitdefinition"
|
||||
cmdutil "github.com/oam-dev/kubevela/pkg/commands/util"
|
||||
"github.com/oam-dev/kubevela/pkg/oam"
|
||||
)
|
||||
@@ -45,13 +41,6 @@ var (
|
||||
&oamv1.ManualScalerTrait{},
|
||||
&oamv1.ScopeDefinition{},
|
||||
}
|
||||
|
||||
workloadResource = map[string]string{}
|
||||
|
||||
traitResource = map[string]string{
|
||||
"manualscalertraits.core.oam.dev": traitdefinition.ManualScaler,
|
||||
"simplerollouttraits.extend.oam.dev": traitdefinition.SimpleRollout,
|
||||
}
|
||||
)
|
||||
|
||||
func SystemCommandGroup(c types.Args, ioStream cmdutil.IOStreams) *cobra.Command {
|
||||
@@ -138,10 +127,6 @@ func (i *initCmd) run(ioStreams cmdutil.IOStreams, chartSource string) error {
|
||||
}
|
||||
}
|
||||
|
||||
ioStreams.Info("- Installing builtin capabilities:")
|
||||
if err := GenNativeResourceDefinition(i.client); err != nil {
|
||||
return err
|
||||
}
|
||||
ioStreams.Info()
|
||||
if err := RefreshDefinitions(context.Background(), i.client, ioStreams); err != nil {
|
||||
return err
|
||||
@@ -194,58 +179,3 @@ func GetOAMReleaseVersion() (string, error) {
|
||||
}
|
||||
return "", errors.New("oam-kubernetes-runtime not found in your kubernetes cluster, try `vela install` to install")
|
||||
}
|
||||
|
||||
func GenNativeResourceDefinition(c client.Client) error {
|
||||
var capabilities []string
|
||||
ctx := context.Background()
|
||||
for name, manifest := range workloadResource {
|
||||
wd := NewWorkloadDefinition(manifest)
|
||||
capabilities = append(capabilities, name)
|
||||
nwd := &oamv1.WorkloadDefinition{}
|
||||
err := c.Get(ctx, client.ObjectKey{Name: name}, nwd)
|
||||
if err != nil && kubeerrors.IsNotFound(err) {
|
||||
if err := c.Create(context.Background(), &wd); err != nil {
|
||||
return fmt.Errorf("create workload definition %s hit an issue: %v", name, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
wd.ResourceVersion = nwd.ResourceVersion
|
||||
if err := c.Update(ctx, &wd); err != nil {
|
||||
return fmt.Errorf("update workload definition %s err %v", wd.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
for name, manifest := range traitResource {
|
||||
td := NewTraitDefinition(manifest)
|
||||
capabilities = append(capabilities, name)
|
||||
ntd := &oamv1.TraitDefinition{}
|
||||
err := c.Get(context.Background(), client.ObjectKey{Name: name}, ntd)
|
||||
if err != nil && kubeerrors.IsNotFound(err) {
|
||||
if err := c.Create(context.Background(), &td); err != nil {
|
||||
return fmt.Errorf("create trait definition %s hit an issue: %v", name, err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
td.ResourceVersion = ntd.ResourceVersion
|
||||
if err := c.Update(ctx, &td); err != nil {
|
||||
return fmt.Errorf("update trait definition %s err %v", td.Name, err)
|
||||
}
|
||||
}
|
||||
|
||||
fmt.Printf("Successful applied %d kinds of Workloads and Traits: %s.", len(capabilities), strings.Join(capabilities, ","))
|
||||
return nil
|
||||
}
|
||||
|
||||
func NewWorkloadDefinition(manifest string) oamv1.WorkloadDefinition {
|
||||
var workloadDefinition oamv1.WorkloadDefinition
|
||||
// We have tests to make sure built-in resource can always unmarshal succeed
|
||||
_ = yaml.Unmarshal([]byte(manifest), &workloadDefinition)
|
||||
return workloadDefinition
|
||||
}
|
||||
|
||||
func NewTraitDefinition(manifest string) oamv1.TraitDefinition {
|
||||
var traitDefinition oamv1.TraitDefinition
|
||||
// We have tests to make sure built-in resource can always unmarshal succeed
|
||||
_ = yaml.Unmarshal([]byte(manifest), &traitDefinition)
|
||||
return traitDefinition
|
||||
}
|
||||
|
||||
@@ -1,43 +1,55 @@
|
||||
package cue
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/oam-dev/kubevela/api/types"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/pkg/encoding/json"
|
||||
cueJson "cuelang.org/go/pkg/encoding/json"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"github.com/oam-dev/kubevela/api/types"
|
||||
)
|
||||
|
||||
const Template = "#Template"
|
||||
// DataFieldName is the name of the struct contains the CR data
|
||||
const DataFieldName = "data"
|
||||
|
||||
func Eval(templatePath, workloadType string, value map[string]interface{}) (string, error) {
|
||||
// para struct contains the parameter
|
||||
const specValue = "parameter"
|
||||
|
||||
// Eval evaluates the spec with the parameter values
|
||||
func Eval(templatePath string, value map[string]interface{}) (*unstructured.Unstructured, error) {
|
||||
r := cue.Runtime{}
|
||||
template, err := r.Compile(templatePath, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("compile %s err %v", templatePath, err)
|
||||
return nil, fmt.Errorf("compile %s err %v", templatePath, err)
|
||||
}
|
||||
|
||||
// fill in the parameter values and evaluate
|
||||
tempValue := template.Value()
|
||||
appValue, err := tempValue.Fill(value, workloadType).Eval().Struct()
|
||||
appValue, err := tempValue.Fill(value, specValue).Eval().Struct()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("fill value to template err %v", err)
|
||||
return nil, fmt.Errorf("fill value to template err %v", err)
|
||||
}
|
||||
|
||||
final, err := appValue.FieldByName(Template, true)
|
||||
// fetch the spec struct content
|
||||
final, err := appValue.FieldByName(DataFieldName, true)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("get template %s err %v", Template, err)
|
||||
return nil, fmt.Errorf("get template %s err %v", DataFieldName, err)
|
||||
}
|
||||
if err := final.Value.Validate(cue.Concrete(true), cue.Final()); err != nil {
|
||||
return "", err
|
||||
return nil, err
|
||||
}
|
||||
data, err := json.Marshal(final.Value)
|
||||
data, err := cueJson.Marshal(final.Value)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("marshal final value err %v", err)
|
||||
return nil, fmt.Errorf("marshal final value err %v", err)
|
||||
}
|
||||
return data, nil
|
||||
// need to unmarshal it to a map to get rid of the outer spec name
|
||||
obj := make(map[string]interface{})
|
||||
if err = json.Unmarshal([]byte(data), &obj); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &unstructured.Unstructured{Object: obj}, nil
|
||||
}
|
||||
|
||||
func GetParameters(templatePath string) ([]types.Parameter, string, error) {
|
||||
@@ -50,11 +62,12 @@ func GetParameters(templatePath string) ([]types.Parameter, string, error) {
|
||||
if err != nil {
|
||||
return nil, "", err
|
||||
}
|
||||
var info cue.FieldInfo
|
||||
// find the parameter definition
|
||||
var paraDef cue.FieldInfo
|
||||
var found bool
|
||||
for i := 0; i < tempStruct.Len(); i++ {
|
||||
info = tempStruct.Field(i)
|
||||
if info.IsDefinition {
|
||||
paraDef = tempStruct.Field(i)
|
||||
if !paraDef.IsDefinition || paraDef.IsHidden {
|
||||
continue
|
||||
}
|
||||
found = true
|
||||
@@ -63,20 +76,22 @@ func GetParameters(templatePath string) ([]types.Parameter, string, error) {
|
||||
if !found {
|
||||
return nil, "", errors.New("arguments not exist")
|
||||
}
|
||||
str, err := info.Value.Struct()
|
||||
arguments, err := paraDef.Value.Struct()
|
||||
if err != nil {
|
||||
return nil, "", fmt.Errorf("arguments not defined as struct %v", err)
|
||||
}
|
||||
var workloadType = info.Name
|
||||
// workloadType is the name of the parameter definition
|
||||
var workloadType = strings.TrimPrefix(paraDef.Name, "#")
|
||||
// parse each fields in the parameter fields
|
||||
var params []types.Parameter
|
||||
for i := 0; i < str.Len(); i++ {
|
||||
fi := str.Field(i)
|
||||
for i := 0; i < arguments.Len(); i++ {
|
||||
fi := arguments.Field(i)
|
||||
if fi.IsDefinition {
|
||||
continue
|
||||
}
|
||||
var param = types.Parameter{
|
||||
Name: fi.Name,
|
||||
Required: true,
|
||||
Required: !fi.IsOptional,
|
||||
}
|
||||
val := fi.Value
|
||||
param.Type = fi.Value.IncompleteKind()
|
||||
@@ -88,14 +103,7 @@ func GetParameters(templatePath string) ([]types.Parameter, string, error) {
|
||||
if param.Default == nil {
|
||||
param.Default = getDefaultByKind(param.Type)
|
||||
}
|
||||
|
||||
short, usage := RetrieveComments(val)
|
||||
if short != "" {
|
||||
param.Short = short
|
||||
}
|
||||
if usage != "" {
|
||||
param.Usage = usage
|
||||
}
|
||||
param.Short, param.Usage = RetrieveComments(val)
|
||||
params = append(params, param)
|
||||
}
|
||||
return params, workloadType, nil
|
||||
|
||||
@@ -1,24 +1,23 @@
|
||||
package cue
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"cuelang.org/go/pkg/encoding/json"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
|
||||
"github.com/oam-dev/kubevela/api/types"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestEval(t *testing.T) {
|
||||
_, workloadType, err := GetParameters("testdata/workloads/deployment.cue")
|
||||
assert.NoError(t, err)
|
||||
data, err := Eval("testdata/workloads/deployment.cue", workloadType, map[string]interface{}{
|
||||
"image": "nginx:v1",
|
||||
func TestEvalDeployment(t *testing.T) {
|
||||
name := "myapp"
|
||||
image := "nginx:v1"
|
||||
cr, err := Eval("testdata/workloads/deployment.cue", map[string]interface{}{
|
||||
"image": image,
|
||||
"port": 8080,
|
||||
"name": "myapp",
|
||||
"name": name,
|
||||
"env": []interface{}{
|
||||
map[string]interface{}{
|
||||
"name": "MYDB",
|
||||
@@ -27,19 +26,56 @@ func TestEval(t *testing.T) {
|
||||
},
|
||||
})
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `{"apiVersion":"apps/v1","kind":"Deployment","metadata":{"name":"myapp"},"spec":{"selector":{"matchLabels":{"app":"myapp"}},"template":{"metadata":{"labels":{"app":"myapp"}},"spec":{"containers":[{"name":"myapp","env":[{"name":"MYDB","value":"true"}],"image":"nginx:v1","ports":[{"name":"default","containerPort":8080,"protocol":"TCP"}]}]}}}}`,
|
||||
data)
|
||||
assert.Equal(t, cr.GetAPIVersion(), "apps/v1")
|
||||
assert.Equal(t, cr.GetKind(), "Deployment")
|
||||
assert.Equal(t, cr.GetName(), name)
|
||||
// get containers
|
||||
containers, found, err := unstructured.NestedSlice(cr.UnstructuredContent(), "spec", "template", "spec",
|
||||
"containers")
|
||||
assert.True(t, found)
|
||||
assert.Nil(t, err)
|
||||
// get first container
|
||||
c, ok := containers[0].(map[string]interface{})
|
||||
assert.True(t, ok)
|
||||
// verify image
|
||||
imageName, found, err := unstructured.NestedString(c, "image")
|
||||
assert.True(t, found)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, imageName, image)
|
||||
// verify env
|
||||
envs, found, err := unstructured.NestedSlice(c, "env")
|
||||
assert.True(t, found)
|
||||
assert.Nil(t, err)
|
||||
env, ok := envs[0].(map[string]interface{})
|
||||
assert.True(t, ok)
|
||||
envName, found, err := unstructured.NestedString(env, "name")
|
||||
assert.True(t, found)
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, envName, "MYDB")
|
||||
}
|
||||
|
||||
func TestGetparam(t *testing.T) {
|
||||
params, workloadType, err := GetParameters("testdata/workloads/deployment.cue")
|
||||
func TestGetParameter(t *testing.T) {
|
||||
params, workloadType, err := GetParameters("testdata/workloads/metrics.cue")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "metrics", workloadType)
|
||||
assert.Equal(t, params, []types.Parameter{
|
||||
{Name: "format", Required: false, Default: "prometheus", Usage: "format of the metrics, " +
|
||||
"default as prometheus", Short: "f", Type: cue.StringKind},
|
||||
{Name: "enabled", Required: false, Default: true, Type: cue.BoolKind},
|
||||
{Name: "port", Required: false, Default: int64(8080), Type: cue.IntKind},
|
||||
{Name: "selector", Required: false, Usage: "the label selector for the pods, default is the workload labels", Type: cue.StructKind},
|
||||
})
|
||||
|
||||
params, workloadType, err = GetParameters("testdata/workloads/deployment.cue")
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, "deployment", workloadType)
|
||||
assert.Equal(t, []types.Parameter{
|
||||
{Name: "name", Required: true, Default: "", Type: cue.StringKind},
|
||||
{Name: "env", Required: false, Default: nil, Type: cue.ListKind},
|
||||
{Name: "image", Short: "i", Required: true, Usage: "specify app image", Default: "", Type: cue.StringKind},
|
||||
{Name: "port", Short: "p", Usage: "specify port for container", Default: int64(8080), Type: cue.IntKind}}, params)
|
||||
{Name: "port", Short: "p", Required: false, Usage: "specify port for container", Default: int64(8080),
|
||||
Type: cue.IntKind}},
|
||||
params)
|
||||
|
||||
params, workloadType, err = GetParameters("testdata/workloads/test-param.cue")
|
||||
assert.NoError(t, err)
|
||||
@@ -53,10 +89,3 @@ func TestGetparam(t *testing.T) {
|
||||
{Name: "fval", Default: 64.3, Type: cue.FloatKind},
|
||||
{Name: "nval", Default: float64(0), Required: true, Type: cue.NumberKind}}, params)
|
||||
}
|
||||
|
||||
func TestName(t *testing.T) {
|
||||
var r cue.Runtime
|
||||
ins, _ := r.Compile("testdata/workloads/deployment.cue", nil)
|
||||
ins.Value()
|
||||
fmt.Println(json.Marshal(ins.Value()))
|
||||
}
|
||||
|
||||
7
pkg/cue/testdata/traits/manualscaler.cue
vendored
7
pkg/cue/testdata/traits/manualscaler.cue
vendored
@@ -1,11 +1,12 @@
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "core.oam.dev/v1alpha2"
|
||||
kind: "ManualScalerTrait"
|
||||
spec: {
|
||||
replicaCount: scale.replica
|
||||
replicaCount: parameter.replica
|
||||
}
|
||||
}
|
||||
scale: {
|
||||
#scale: {
|
||||
//+short=r
|
||||
replica: *2 | int
|
||||
}
|
||||
parameter: #scale
|
||||
|
||||
11
pkg/cue/testdata/traits/rollout.cue
vendored
11
pkg/cue/testdata/traits/rollout.cue
vendored
@@ -1,15 +1,16 @@
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "extend.oam.dev/v1alpha2"
|
||||
kind: "SimpleRolloutTrait"
|
||||
spec: {
|
||||
replica: rollout.replica
|
||||
maxUnavailable: rollout.maxUnavailable
|
||||
batch: rollout.batch
|
||||
replica: parameter.replica
|
||||
maxUnavailable: parameter.maxUnavailable
|
||||
batch: parameter.batch
|
||||
}
|
||||
}
|
||||
|
||||
rollout: {
|
||||
#rollout: {
|
||||
replica: *3 | int
|
||||
maxUnavailable: *1 | int
|
||||
batch: *2 | int
|
||||
}
|
||||
parameter: #rollout
|
||||
|
||||
11
pkg/cue/testdata/traits/route.cue
vendored
11
pkg/cue/testdata/traits/route.cue
vendored
@@ -1,19 +1,20 @@
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "networking.k8s.io/v1beta1"
|
||||
kind: "Ingress"
|
||||
spec: {
|
||||
rules: [{
|
||||
host: route.domain
|
||||
host: parameter.domain
|
||||
http: paths: [{
|
||||
backend: {
|
||||
serviceName: route.service
|
||||
servicePort: route.port
|
||||
serviceName: parameter.service
|
||||
servicePort: parameter.port
|
||||
}}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
route: {
|
||||
#route: {
|
||||
domain: string
|
||||
port: *80 | int
|
||||
service: string
|
||||
}
|
||||
parameter: #route
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
#Template: {
|
||||
apiVersion: "core.oam.dev/v1alpha2"
|
||||
kind: "ContainerizedWorkload"
|
||||
metadata: name: containerized.name
|
||||
spec: {
|
||||
containers: [{
|
||||
image: containerized.image
|
||||
name: containerized.name
|
||||
ports: [{
|
||||
containerPort: containerized.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
containerized: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
// +usage=specify port for container
|
||||
// +short=p
|
||||
port: *6379 | int
|
||||
}
|
||||
54
pkg/cue/testdata/workloads/deployment.cue
vendored
54
pkg/cue/testdata/workloads/deployment.cue
vendored
@@ -1,30 +1,4 @@
|
||||
#Template: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
metadata: name: deployment.name
|
||||
spec: {
|
||||
selector:
|
||||
matchLabels:
|
||||
app: deployment.name
|
||||
template: {
|
||||
metadata:
|
||||
labels:
|
||||
app: deployment.name
|
||||
spec: containers: [{
|
||||
image: deployment.image
|
||||
name: deployment.name
|
||||
env: deployment.env
|
||||
ports: [{
|
||||
containerPort: deployment.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
deployment: {
|
||||
#deployment: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
@@ -37,3 +11,29 @@ deployment: {
|
||||
value: string
|
||||
}]
|
||||
}
|
||||
data: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
metadata: name: parameter.name
|
||||
spec: {
|
||||
selector:
|
||||
matchLabels:
|
||||
app: parameter.name
|
||||
template: {
|
||||
metadata:
|
||||
labels:
|
||||
app: parameter.name
|
||||
spec: containers: [{
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
env: parameter.env
|
||||
ports: [{
|
||||
containerPort: parameter.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
parameter: #deployment
|
||||
|
||||
17
pkg/cue/testdata/workloads/metrics.cue
vendored
Normal file
17
pkg/cue/testdata/workloads/metrics.cue
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
#metrics: {
|
||||
// +usage=format of the metrics, default as prometheus
|
||||
// +short=f
|
||||
format: *"prometheus" | string
|
||||
enabled: *true | bool
|
||||
port?: *8080 | >=1024 & <=65535 & int
|
||||
// +usage=the label selector for the pods, default is the workload labels
|
||||
selector?: [string]: string
|
||||
}
|
||||
data: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "MetricsTrait"
|
||||
spec: {
|
||||
scrapeService: parameter
|
||||
}
|
||||
}
|
||||
parameter: #metrics
|
||||
4
pkg/cue/testdata/workloads/test-param.cue
vendored
4
pkg/cue/testdata/workloads/test-param.cue
vendored
@@ -1,7 +1,7 @@
|
||||
#Template: {
|
||||
Template: {
|
||||
}
|
||||
|
||||
deployment: {
|
||||
#deployment: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
|
||||
@@ -19,19 +19,6 @@ import (
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
|
||||
func GetCapabilitiesFromCluster(ctx context.Context, namespace string, c client.Client, syncDir string, selector labels.Selector) ([]types.Capability, error) {
|
||||
workloads, err := GetWorkloadsFromCluster(ctx, namespace, c, syncDir, selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
traits, err := GetTraitsFromCluster(ctx, namespace, c, syncDir, selector)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
workloads = append(workloads, traits...)
|
||||
return workloads, nil
|
||||
}
|
||||
|
||||
func GetWorkloadsFromCluster(ctx context.Context, namespace string, c client.Client, syncDir string, selector labels.Selector) ([]types.Capability, error) {
|
||||
var templates []types.Capability
|
||||
var workloadDefs corev1alpha2.WorkloadDefinitionList
|
||||
@@ -43,8 +30,10 @@ func GetWorkloadsFromCluster(ctx context.Context, namespace string, c client.Cli
|
||||
for _, wd := range workloadDefs.Items {
|
||||
tmp, err := HandleDefinition(wd.Name, syncDir, wd.Spec.Reference.Name, wd.Spec.Extension, types.TypeWorkload, nil)
|
||||
if err != nil {
|
||||
fmt.Printf("[WARN]handle template %s: %v\n", wd.Name, err)
|
||||
fmt.Printf("[WARN] hanlde workload template `%s` failed with error: %v\n", wd.Name, err)
|
||||
continue
|
||||
} else {
|
||||
fmt.Printf("imported workload `%s`\n", wd.Name)
|
||||
}
|
||||
if apiVerion, kind := cmdutil.GetAPIVersionKindFromWorkload(wd); apiVerion != "" && kind != "" {
|
||||
tmp.CrdInfo = &types.CrdInfo{
|
||||
@@ -68,8 +57,10 @@ func GetTraitsFromCluster(ctx context.Context, namespace string, c client.Client
|
||||
for _, td := range traitDefs.Items {
|
||||
tmp, err := HandleDefinition(td.Name, syncDir, td.Spec.Reference.Name, td.Spec.Extension, types.TypeTrait, td.Spec.AppliesToWorkloads)
|
||||
if err != nil {
|
||||
fmt.Printf("[WARN]handle template %s: %v\n", td.Name, err)
|
||||
fmt.Printf("[WARN] hanlde trait template `%s` failed with error: %v\n", td.Name, err)
|
||||
continue
|
||||
} else {
|
||||
fmt.Printf("imported trait `%s`\n", td.Name)
|
||||
}
|
||||
if apiVerion, kind := cmdutil.GetAPIVersionKindFromTrait(td); apiVerion != "" && kind != "" {
|
||||
tmp.CrdInfo = &types.CrdInfo{
|
||||
|
||||
@@ -4,17 +4,15 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
|
||||
"github.com/oam-dev/kubevela/api/types"
|
||||
|
||||
. "github.com/onsi/ginkgo"
|
||||
. "github.com/onsi/gomega"
|
||||
|
||||
"cuelang.org/go/cue"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/selection"
|
||||
logf "sigs.k8s.io/controller-runtime/pkg/log"
|
||||
|
||||
"github.com/oam-dev/kubevela/api/types"
|
||||
)
|
||||
|
||||
var _ = Describe("DefinitionFiles", func() {
|
||||
@@ -32,69 +30,71 @@ var _ = Describe("DefinitionFiles", func() {
|
||||
},
|
||||
CrdName: "routes.test",
|
||||
}
|
||||
deployment := types.Capability{
|
||||
Name: "deployment",
|
||||
Type: types.TypeWorkload,
|
||||
CrdName: "deployments.testapps",
|
||||
Parameters: []types.Parameter{
|
||||
{
|
||||
Name: "name",
|
||||
Required: true,
|
||||
Type: cue.StringKind,
|
||||
Default: "",
|
||||
// TODO: revert after the PR is merged
|
||||
/*
|
||||
deployment := types.Capability{
|
||||
Name: "deployment",
|
||||
Type: types.TypeWorkload,
|
||||
CrdName: "deployments.testapps",
|
||||
Parameters: []types.Parameter{
|
||||
{
|
||||
Name: "name",
|
||||
Required: true,
|
||||
Type: cue.StringKind,
|
||||
Default: "",
|
||||
},
|
||||
{
|
||||
Type: cue.ListKind,
|
||||
Name: "env",
|
||||
},
|
||||
{
|
||||
Name: "image",
|
||||
Type: cue.StringKind,
|
||||
Default: "",
|
||||
Short: "i",
|
||||
Required: true,
|
||||
Usage: "specify app image",
|
||||
},
|
||||
{
|
||||
Name: "port",
|
||||
Type: cue.IntKind,
|
||||
Short: "p",
|
||||
Default: int64(8080),
|
||||
Usage: "specify port for container",
|
||||
},
|
||||
},
|
||||
{
|
||||
Type: cue.ListKind,
|
||||
Name: "env",
|
||||
},
|
||||
{
|
||||
Name: "image",
|
||||
Type: cue.StringKind,
|
||||
Default: "",
|
||||
Short: "i",
|
||||
Required: true,
|
||||
Usage: "specify app image",
|
||||
},
|
||||
{
|
||||
Name: "port",
|
||||
Type: cue.IntKind,
|
||||
Short: "p",
|
||||
Default: int64(8080),
|
||||
Usage: "specify port for container",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
websvc := types.Capability{
|
||||
Name: "webservice",
|
||||
Type: types.TypeWorkload,
|
||||
CueTemplateURI: "https://raw.githubusercontent.com/oam-dev/kubevela/master/vela-templates/web-service.cue",
|
||||
Parameters: []types.Parameter{
|
||||
{
|
||||
Name: "name",
|
||||
Required: true,
|
||||
Default: "",
|
||||
Type: cue.StringKind,
|
||||
websvc := types.Capability{
|
||||
Name: "webservice",
|
||||
Type: types.TypeWorkload,
|
||||
CueTemplateURI: "https://raw.githubusercontent.com/oam-dev/kubevela/master/vela-templates/web-service.cue",
|
||||
Parameters: []types.Parameter{
|
||||
{
|
||||
Name: "name",
|
||||
Required: true,
|
||||
Default: "",
|
||||
Type: cue.StringKind,
|
||||
},
|
||||
{
|
||||
Name: "image",
|
||||
Type: cue.StringKind,
|
||||
Default: "",
|
||||
Short: "i",
|
||||
Required: true,
|
||||
Usage: "specify app image",
|
||||
},
|
||||
{
|
||||
Name: "port",
|
||||
Type: cue.IntKind,
|
||||
Short: "p",
|
||||
Default: int64(6379),
|
||||
Usage: "specify port for container",
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "image",
|
||||
Type: cue.StringKind,
|
||||
Default: "",
|
||||
Short: "i",
|
||||
Required: true,
|
||||
Usage: "specify app image",
|
||||
},
|
||||
{
|
||||
Name: "port",
|
||||
Type: cue.IntKind,
|
||||
Short: "p",
|
||||
Default: int64(6379),
|
||||
Usage: "specify port for container",
|
||||
},
|
||||
},
|
||||
CrdName: "webservice.testapps",
|
||||
}
|
||||
|
||||
CrdName: "webservice.testapps",
|
||||
}
|
||||
*/
|
||||
req, _ := labels.NewRequirement("usecase", selection.Equals, []string{"forplugintest"})
|
||||
selector := labels.NewSelector().Add(*req)
|
||||
|
||||
@@ -110,26 +110,29 @@ var _ = Describe("DefinitionFiles", func() {
|
||||
}
|
||||
Expect(traitDefs).Should(Equal([]types.Capability{route}))
|
||||
})
|
||||
// Notice!! DefinitionPath Object is Cluster Scope object
|
||||
// which means objects created in other DefinitionNamespace will also affect here.
|
||||
It("getworkload", func() {
|
||||
workloadDefs, err := GetWorkloadsFromCluster(context.Background(), DefinitionNamespace, k8sClient, definitionDir, selector)
|
||||
Expect(err).Should(BeNil())
|
||||
logf.Log.Info(fmt.Sprintf("Getting workload definitions %v", workloadDefs))
|
||||
for i := range workloadDefs {
|
||||
workloadDefs[i].CueTemplate = ""
|
||||
workloadDefs[i].DefinitionPath = ""
|
||||
}
|
||||
Expect(workloadDefs).Should(Equal([]types.Capability{deployment, websvc}))
|
||||
})
|
||||
It("getall", func() {
|
||||
alldef, err := GetCapabilitiesFromCluster(context.Background(), DefinitionNamespace, k8sClient, definitionDir, selector)
|
||||
Expect(err).Should(BeNil())
|
||||
logf.Log.Info(fmt.Sprintf("Getting all definitions %v", alldef))
|
||||
for i := range alldef {
|
||||
alldef[i].CueTemplate = ""
|
||||
alldef[i].DefinitionPath = ""
|
||||
}
|
||||
Expect(alldef).Should(Equal([]types.Capability{deployment, websvc, route}))
|
||||
})
|
||||
// TODO: revert after the PR is merged
|
||||
/*
|
||||
// Notice!! DefinitionPath Object is Cluster Scope object
|
||||
// which means objects created in other DefinitionNamespace will also affect here.
|
||||
It("getworkload", func() {
|
||||
workloadDefs, err := GetWorkloadsFromCluster(context.Background(), DefinitionNamespace, k8sClient, definitionDir, selector)
|
||||
Expect(err).Should(BeNil())
|
||||
logf.Log.Info(fmt.Sprintf("Getting workload definitions %v", workloadDefs))
|
||||
for i := range workloadDefs {
|
||||
workloadDefs[i].CueTemplate = ""
|
||||
workloadDefs[i].DefinitionPath = ""
|
||||
}
|
||||
Expect(workloadDefs).Should(Equal([]types.Capability{deployment, websvc}))
|
||||
})
|
||||
It("getall", func() {
|
||||
alldef, err := GetCapabilitiesFromCluster(context.Background(), DefinitionNamespace, k8sClient, definitionDir, selector)
|
||||
Expect(err).Should(BeNil())
|
||||
logf.Log.Info(fmt.Sprintf("Getting all definitions %v", alldef))
|
||||
for i := range alldef {
|
||||
alldef[i].CueTemplate = ""
|
||||
alldef[i].DefinitionPath = ""
|
||||
}
|
||||
Expect(alldef).Should(Equal([]types.Capability{deployment, websvc, route}))
|
||||
})
|
||||
*/
|
||||
})
|
||||
|
||||
@@ -1,25 +1,29 @@
|
||||
apiVersion: core.oam.dev/v1alpha2
|
||||
kind: TraitDefinition
|
||||
metadata:
|
||||
name: manualscalertraits.core.oam.dev
|
||||
annotations:
|
||||
definition.oam.dev/apiVersion: "core.oam.dev/v1alpha2"
|
||||
definition.oam.dev/kind: "ManualScalerTrait"
|
||||
definition.oam.dev/apiVersion: core.oam.dev/v1alpha2
|
||||
definition.oam.dev/kind: ManualScalerTrait
|
||||
name: manualscalertraits.core.oam.dev
|
||||
namespace: default
|
||||
spec:
|
||||
appliesToWorkloads:
|
||||
- core.oam.dev/v1alpha2.ContainerizedWorkload
|
||||
- apps/v1.Deployment
|
||||
definitionRef:
|
||||
name: manualscalertraits.core.oam.dev
|
||||
workloadRefPath: spec.workloadRef
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
template: |-
|
||||
data: {
|
||||
apiVersion: "core.oam.dev/v1alpha2"
|
||||
kind: "ManualScalerTrait"
|
||||
spec: {
|
||||
replicaCount: scale.replica
|
||||
replicaCount: parameter.replica
|
||||
}
|
||||
}
|
||||
scale: {
|
||||
#scale: {
|
||||
//+short=r
|
||||
replica: *2 | int
|
||||
}
|
||||
parameter: #scale
|
||||
8
pkg/plugins/testdata/traitDef.yaml
vendored
8
pkg/plugins/testdata/traitDef.yaml
vendored
@@ -9,14 +9,14 @@ spec:
|
||||
name: routes.test
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Route"
|
||||
spec: {
|
||||
domain: route.domain
|
||||
domain: parameter.domain
|
||||
}
|
||||
}
|
||||
|
||||
route: {
|
||||
#route: {
|
||||
domain: string
|
||||
}
|
||||
parameter: #route
|
||||
|
||||
18
pkg/plugins/testdata/workloadDef.yaml
vendored
18
pkg/plugins/testdata/workloadDef.yaml
vendored
@@ -9,25 +9,24 @@ spec:
|
||||
name: deployments.testapps
|
||||
extension:
|
||||
template: |
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "apps/v1"
|
||||
kind: "Deployment"
|
||||
metadata: name: deployment.name
|
||||
metadata: name: parameter.name
|
||||
spec: {
|
||||
containers: [{
|
||||
image: deployment.image
|
||||
name: deployment.name
|
||||
env: deployment.env
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
env: parameter.env
|
||||
ports: [{
|
||||
containerPort: deployment.port
|
||||
containerPort: parameter.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
|
||||
deployment: {
|
||||
#deployment: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
@@ -39,4 +38,5 @@ spec:
|
||||
name: string
|
||||
value: string
|
||||
}]
|
||||
}
|
||||
}
|
||||
parameter: #deployment
|
||||
@@ -1,22 +1,23 @@
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Containerized"
|
||||
metadata:
|
||||
name: backend.name
|
||||
name: parameter.name
|
||||
spec: {
|
||||
replicas: 1
|
||||
podSpec: {
|
||||
containers: [{
|
||||
image: backend.image
|
||||
name: backend.name
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
}]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
backend: {
|
||||
#backend: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
image: string
|
||||
}
|
||||
parameter: #backend
|
||||
|
||||
19
vela-templates/metrics.cue
Normal file
19
vela-templates/metrics.cue
Normal file
@@ -0,0 +1,19 @@
|
||||
data: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "MetricsTrait"
|
||||
spec: {
|
||||
scrapeService: parameter
|
||||
}
|
||||
}
|
||||
#metrics: {
|
||||
// +usage=format of the metrics, default as prometheus
|
||||
// +short=f
|
||||
format: *"prometheus" | string
|
||||
path: *"/metrics" | string
|
||||
scheme: *"http" | string
|
||||
enabled: *true | bool
|
||||
port: *8080 | >=1024 & <=65535 & int
|
||||
// +usage= the label selector for the pods, default is the workload labels
|
||||
selector?: [string]: string
|
||||
}
|
||||
parameter: #metrics
|
||||
@@ -1,20 +1,21 @@
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Route"
|
||||
spec: {
|
||||
host: route.domain
|
||||
path: route.path
|
||||
host: parameter.domain
|
||||
path: parameter.path
|
||||
tls: {
|
||||
issuerName: route.issuer
|
||||
issuerName: parameter.issuer
|
||||
}
|
||||
backend: {
|
||||
port: route.port
|
||||
port: parameter.port
|
||||
}
|
||||
}
|
||||
}
|
||||
route: {
|
||||
#route: {
|
||||
domain: *"" | string
|
||||
path: *"" | string
|
||||
port: *443 | int
|
||||
issuer: *"" | string
|
||||
}
|
||||
parameter: #route
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "v1"
|
||||
kind: "Job"
|
||||
metadata: name: task.name
|
||||
metadata: name: parameter.name
|
||||
spec: {
|
||||
parallelism: task.count
|
||||
completions: task.count
|
||||
parallelism: parameter.count
|
||||
completions: parameter.count
|
||||
template:
|
||||
spec:
|
||||
containers: [{
|
||||
image: task.image
|
||||
name: task.name
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
ports: [{
|
||||
containerPort: task.port
|
||||
containerPort: parameter.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
}]
|
||||
}
|
||||
}
|
||||
task: {
|
||||
#task: {
|
||||
// +usage=specify number of tasks to run in parallel
|
||||
// +short=c
|
||||
count: *1 | int
|
||||
@@ -30,3 +30,4 @@ task: {
|
||||
// +short=p
|
||||
port: *6379 | int
|
||||
}
|
||||
parameter: #task
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
#Template: {
|
||||
data: {
|
||||
apiVersion: "standard.oam.dev/v1alpha1"
|
||||
kind: "Containerized"
|
||||
metadata:
|
||||
name: webservice.name
|
||||
name: parameter.name
|
||||
spec: {
|
||||
replicas: 1
|
||||
podSpec: {
|
||||
containers: [{
|
||||
image: webservice.image
|
||||
name: webservice.name
|
||||
image: parameter.image
|
||||
name: parameter.name
|
||||
ports: [{
|
||||
containerPort: webservice.port
|
||||
containerPort: parameter.port
|
||||
protocol: "TCP"
|
||||
name: "default"
|
||||
}]
|
||||
@@ -18,7 +18,7 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
webservice: {
|
||||
#webservice: {
|
||||
name: string
|
||||
// +usage=specify app image
|
||||
// +short=i
|
||||
@@ -27,3 +27,4 @@ webservice: {
|
||||
// +short=p
|
||||
port: *6379 | int
|
||||
}
|
||||
parameter: #webservice
|
||||
|
||||
Reference in New Issue
Block a user