diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index 6aa7ad560..1d435e823 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -64,6 +64,45 @@ jobs: flags: unittests name: codecov-umbrella + compatibility-test: + runs-on: ubuntu-20.04 + steps: + - name: Set up Go 1.14 + uses: actions/setup-go@v1 + with: + go-version: ${{ env.GO_VERSION }} + id: go + + - name: Check out code into the Go module directory + uses: actions/checkout@v2 + with: + submodules: true + + - name: Cache Go Dependencies + uses: actions/cache@v2 + with: + path: .work/pkg + key: ${{ runner.os }}-pkg-${{ hashFiles('**/go.sum') }} + restore-keys: ${{ runner.os }}-pkg- + + - name: Install ginkgo + run: | + sudo apt-get install -y golang-ginkgo-dev + + - name: Setup Kind Cluster + uses: engineerd/setup-kind@v0.5.0 + with: + version: ${{ env.KIND_VERSION }} + + - name: install Kubebuilder + uses: wonderflow/kubebuilder-action@v1.1 + + - name: Run Make compatibility-test + run: make compatibility-test + + - name: Clean up testdata + run: make compatibility-testdata-cleanup + e2e-tests: runs-on: aliyun steps: diff --git a/Makefile b/Makefile index a7ee439ee..240d9e716 100644 --- a/Makefile +++ b/Makefile @@ -144,6 +144,18 @@ e2e-test: CGO_ENABLED=0 go test -timeout 1h -count=1 -v -tags 'integration' ./test/integration @$(OK) tests pass +compatibility-test: vet lint staticcheck generate-compatibility-testdata + # Run compatibility test with old crd + COMPATIBILITY_TEST=TRUE go test -race ./pkg/... + @$(OK) compatibility-test pass + +generate-compatibility-testdata: + mkdir -p ./test/compatibility-test/testdata + go run ./test/compatibility-test/convert/main.go ./charts/vela-core/crds ./test/compatibility-test/testdata + +compatibility-testdata-cleanup: + rm -f ./test/compatibility-test/testdata/* + e2e-cleanup: # Clean up rm -rf ~/.vela diff --git a/apis/core.oam.dev/v1alpha2/core_types.go b/apis/core.oam.dev/v1alpha2/core_types.go index 8360afd46..66cf0ff83 100644 --- a/apis/core.oam.dev/v1alpha2/core_types.go +++ b/apis/core.oam.dev/v1alpha2/core_types.go @@ -101,7 +101,7 @@ type Status struct { // is used to validate the schema of the workload when it is embedded in an OAM // Component. // +kubebuilder:printcolumn:JSONPath=".spec.definitionRef.name",name=DEFINITION-NAME,type=string -// +kubebuilder:resource:scope=Cluster,categories={crossplane,oam} +// +kubebuilder:resource:scope=Namespaced,categories={crossplane,oam} type WorkloadDefinition struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -177,7 +177,7 @@ type TraitDefinitionSpec struct { // to validate the schema of the trait when it is embedded in an OAM // ApplicationConfiguration. // +kubebuilder:printcolumn:JSONPath=".spec.definitionRef.name",name=DEFINITION-NAME,type=string -// +kubebuilder:resource:scope=Cluster,categories={crossplane,oam} +// +kubebuilder:resource:scope=Namespaced,categories={crossplane,oam} type TraitDefinition struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` @@ -219,7 +219,7 @@ type ScopeDefinitionSpec struct { // to validate the schema of the scope when it is embedded in an OAM // ApplicationConfiguration. // +kubebuilder:printcolumn:JSONPath=".spec.definitionRef.name",name=DEFINITION-NAME,type=string -// +kubebuilder:resource:scope=Cluster,categories={crossplane,oam} +// +kubebuilder:resource:scope=Namespaced,categories={crossplane,oam} type ScopeDefinition struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` diff --git a/charts/vela-core/crds/core.oam.dev_scopedefinitions.yaml b/charts/vela-core/crds/core.oam.dev_scopedefinitions.yaml index c64acc562..070e2dd48 100644 --- a/charts/vela-core/crds/core.oam.dev_scopedefinitions.yaml +++ b/charts/vela-core/crds/core.oam.dev_scopedefinitions.yaml @@ -17,7 +17,7 @@ spec: listKind: ScopeDefinitionList plural: scopedefinitions singular: scopedefinition - scope: Cluster + scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.definitionRef.name diff --git a/charts/vela-core/crds/core.oam.dev_traitdefinitions.yaml b/charts/vela-core/crds/core.oam.dev_traitdefinitions.yaml index ac0ff3ac2..bd0d4b4e3 100644 --- a/charts/vela-core/crds/core.oam.dev_traitdefinitions.yaml +++ b/charts/vela-core/crds/core.oam.dev_traitdefinitions.yaml @@ -17,7 +17,7 @@ spec: listKind: TraitDefinitionList plural: traitdefinitions singular: traitdefinition - scope: Cluster + scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.definitionRef.name diff --git a/charts/vela-core/crds/core.oam.dev_workloaddefinitions.yaml b/charts/vela-core/crds/core.oam.dev_workloaddefinitions.yaml index 15afb139b..440113abf 100644 --- a/charts/vela-core/crds/core.oam.dev_workloaddefinitions.yaml +++ b/charts/vela-core/crds/core.oam.dev_workloaddefinitions.yaml @@ -17,7 +17,7 @@ spec: listKind: WorkloadDefinitionList plural: workloaddefinitions singular: workloaddefinition - scope: Cluster + scope: Namespaced versions: - additionalPrinterColumns: - jsonPath: .spec.definitionRef.name diff --git a/charts/vela-core/templates/definitions/containerizedworkloads.yaml b/charts/vela-core/templates/definitions/containerizedworkloads.yaml index ad79b971d..dbda172a4 100644 --- a/charts/vela-core/templates/definitions/containerizedworkloads.yaml +++ b/charts/vela-core/templates/definitions/containerizedworkloads.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: containerizedworkloads.core.oam.dev + namespace: {{.Values.systemDefinitionNamespace}} spec: definitionRef: name: containerizedworkloads.core.oam.dev diff --git a/charts/vela-core/templates/definitions/healthscopes.yaml b/charts/vela-core/templates/definitions/healthscopes.yaml index d3cc95db3..5eb3129e3 100644 --- a/charts/vela-core/templates/definitions/healthscopes.yaml +++ b/charts/vela-core/templates/definitions/healthscopes.yaml @@ -2,7 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: ScopeDefinition metadata: name: healthscopes.core.oam.dev - namespace: default + namespace: {{.Values.systemDefinitionNamespace}} spec: workloadRefsPath: spec.workloadRefs allowComponentOverlap: true diff --git a/charts/vela-core/templates/defwithtemplate/ingress.yaml b/charts/vela-core/templates/defwithtemplate/ingress.yaml index 540b88f2d..d8be40db0 100644 --- a/charts/vela-core/templates/defwithtemplate/ingress.yaml +++ b/charts/vela-core/templates/defwithtemplate/ingress.yaml @@ -6,6 +6,7 @@ metadata: definition.oam.dev/description: "Configures K8s ingress and service to enable web traffic for your service. Please use route trait in cap center for advanced usage." name: ingress + namespace: {{.Values.systemDefinitionNamespace}} spec: status: customStatus: |- diff --git a/charts/vela-core/templates/defwithtemplate/manualscale.yaml b/charts/vela-core/templates/defwithtemplate/manualscale.yaml index 3fe214c37..aae75edf5 100644 --- a/charts/vela-core/templates/defwithtemplate/manualscale.yaml +++ b/charts/vela-core/templates/defwithtemplate/manualscale.yaml @@ -5,6 +5,7 @@ metadata: annotations: definition.oam.dev/description: "Configures replicas for your service." name: scaler + namespace: {{.Values.systemDefinitionNamespace}} spec: appliesToWorkloads: - webservice diff --git a/charts/vela-core/templates/defwithtemplate/task.yaml b/charts/vela-core/templates/defwithtemplate/task.yaml index 98f937559..7cc5f1868 100644 --- a/charts/vela-core/templates/defwithtemplate/task.yaml +++ b/charts/vela-core/templates/defwithtemplate/task.yaml @@ -3,6 +3,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: task + namespace: {{.Values.systemDefinitionNamespace}} annotations: definition.oam.dev/description: "Describes jobs that run code or a script to completion." spec: diff --git a/charts/vela-core/templates/defwithtemplate/webservice.yaml b/charts/vela-core/templates/defwithtemplate/webservice.yaml index f808db89a..0f8056e81 100644 --- a/charts/vela-core/templates/defwithtemplate/webservice.yaml +++ b/charts/vela-core/templates/defwithtemplate/webservice.yaml @@ -3,6 +3,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: webservice + namespace: {{.Values.systemDefinitionNamespace}} annotations: definition.oam.dev/description: "Describes long-running, scalable, containerized services that have a stable network endpoint to receive external network traffic from customers. If workload type is skipped for any service defined in Appfile, it will be defaulted to `webservice` type." diff --git a/charts/vela-core/templates/defwithtemplate/worker.yaml b/charts/vela-core/templates/defwithtemplate/worker.yaml index 9ddeecb62..f1f15fd52 100644 --- a/charts/vela-core/templates/defwithtemplate/worker.yaml +++ b/charts/vela-core/templates/defwithtemplate/worker.yaml @@ -3,6 +3,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: worker + namespace: {{.Values.systemDefinitionNamespace}} annotations: definition.oam.dev/description: "Describes long-running, scalable, containerized services that running at backend. They do NOT have network endpoint to receive external network traffic." spec: diff --git a/charts/vela-core/values.yaml b/charts/vela-core/values.yaml index a055f1a0f..28aca19b3 100644 --- a/charts/vela-core/values.yaml +++ b/charts/vela-core/values.yaml @@ -84,3 +84,5 @@ certificate: secretName: webhook-server-cert mountPath: /etc/k8s-webhook-certs caBundle: replace-me + +systemDefinitionNamespace: vela-system diff --git a/cmd/core/main.go b/cmd/core/main.go index d27f5ac45..3016056ed 100644 --- a/cmd/core/main.go +++ b/cmd/core/main.go @@ -38,6 +38,7 @@ import ( oamcontroller "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev" oamv1alpha2 "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/pkg/controller/utils" + "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/utils/system" oamwebhook "github.com/oam-dev/kubevela/pkg/webhook/core.oam.dev" velawebhook "github.com/oam-dev/kubevela/pkg/webhook/standard.oam.dev" @@ -105,6 +106,7 @@ func main() { flag.StringVar(&storageDriver, "storage-driver", driver.LocalDriverName, "Application file save to the storage driver") flag.DurationVar(&syncPeriod, "informer-re-sync-interval", 5*time.Minute, "controller shared informer lister full re-sync period") + flag.StringVar(&oam.SystemDefinitonNamespace, "system-definition-namespace", "vela-system", "define the namespace of the system-level definition") flag.Parse() // setup logging @@ -126,6 +128,7 @@ func main() { setupLog.Info(fmt.Sprintf("KubeVela Version: %s, GIT Revision: %s.", version.VelaVersion, version.GitRevision)) setupLog.Info(fmt.Sprintf("Disable Capabilities: %s.", disableCaps)) + setupLog.Info(fmt.Sprintf("core init with definition namespace %s", oam.SystemDefinitonNamespace)) restConfig := ctrl.GetConfigOrDie() restConfig.UserAgent = kubevelaName + "/" + version.GitRevision diff --git a/hack/vela-templates/definitions/ingress.yaml b/hack/vela-templates/definitions/ingress.yaml index fd0bb9959..4ab7c0b48 100644 --- a/hack/vela-templates/definitions/ingress.yaml +++ b/hack/vela-templates/definitions/ingress.yaml @@ -5,6 +5,7 @@ metadata: definition.oam.dev/description: "Configures K8s ingress and service to enable web traffic for your service. Please use route trait in cap center for advanced usage." name: ingress + namespace: {{.Values.systemDefinitionNamespace}} spec: status: customStatus: |- diff --git a/hack/vela-templates/definitions/manualscale.yaml b/hack/vela-templates/definitions/manualscale.yaml index 246291d44..d8595d6f6 100644 --- a/hack/vela-templates/definitions/manualscale.yaml +++ b/hack/vela-templates/definitions/manualscale.yaml @@ -4,6 +4,7 @@ metadata: annotations: definition.oam.dev/description: "Configures replicas for your service." name: scaler + namespace: {{.Values.systemDefinitionNamespace}} spec: appliesToWorkloads: - webservice diff --git a/hack/vela-templates/definitions/task.yaml b/hack/vela-templates/definitions/task.yaml index 525794a31..3fe5cc5a7 100644 --- a/hack/vela-templates/definitions/task.yaml +++ b/hack/vela-templates/definitions/task.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: task + namespace: {{.Values.systemDefinitionNamespace}} annotations: definition.oam.dev/description: "Describes jobs that run code or a script to completion." spec: diff --git a/hack/vela-templates/definitions/webservice.yaml b/hack/vela-templates/definitions/webservice.yaml index ca03df0dc..98e02ae94 100644 --- a/hack/vela-templates/definitions/webservice.yaml +++ b/hack/vela-templates/definitions/webservice.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: webservice + namespace: {{.Values.systemDefinitionNamespace}} annotations: definition.oam.dev/description: "Describes long-running, scalable, containerized services that have a stable network endpoint to receive external network traffic from customers. If workload type is skipped for any service defined in Appfile, it will be defaulted to `webservice` type." diff --git a/hack/vela-templates/definitions/worker.yaml b/hack/vela-templates/definitions/worker.yaml index 9aea430c5..e0498d660 100644 --- a/hack/vela-templates/definitions/worker.yaml +++ b/hack/vela-templates/definitions/worker.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: worker + namespace: {{.Values.systemDefinitionNamespace}} annotations: definition.oam.dev/description: "Describes long-running, scalable, containerized services that running at backend. They do NOT have network endpoint to receive external network traffic." spec: diff --git a/legacy/charts/vela-core-legacy/crds/core.oam.dev_scopedefinitions.yaml b/legacy/charts/vela-core-legacy/crds/core.oam.dev_scopedefinitions.yaml index 56742c7fd..ba7464566 100644 --- a/legacy/charts/vela-core-legacy/crds/core.oam.dev_scopedefinitions.yaml +++ b/legacy/charts/vela-core-legacy/crds/core.oam.dev_scopedefinitions.yaml @@ -21,7 +21,7 @@ spec: listKind: ScopeDefinitionList plural: scopedefinitions singular: scopedefinition - scope: Cluster + scope: Namespaced subresources: {} validation: openAPIV3Schema: diff --git a/legacy/charts/vela-core-legacy/crds/core.oam.dev_traitdefinitions.yaml b/legacy/charts/vela-core-legacy/crds/core.oam.dev_traitdefinitions.yaml index a3093d35b..ade7f5edd 100644 --- a/legacy/charts/vela-core-legacy/crds/core.oam.dev_traitdefinitions.yaml +++ b/legacy/charts/vela-core-legacy/crds/core.oam.dev_traitdefinitions.yaml @@ -21,7 +21,7 @@ spec: listKind: TraitDefinitionList plural: traitdefinitions singular: traitdefinition - scope: Cluster + scope: Namespaced subresources: {} validation: openAPIV3Schema: diff --git a/legacy/charts/vela-core-legacy/crds/core.oam.dev_workloaddefinitions.yaml b/legacy/charts/vela-core-legacy/crds/core.oam.dev_workloaddefinitions.yaml index 28ecc1a4e..0ae854f2a 100644 --- a/legacy/charts/vela-core-legacy/crds/core.oam.dev_workloaddefinitions.yaml +++ b/legacy/charts/vela-core-legacy/crds/core.oam.dev_workloaddefinitions.yaml @@ -21,7 +21,7 @@ spec: listKind: WorkloadDefinitionList plural: workloaddefinitions singular: workloaddefinition - scope: Cluster + scope: Namespaced subresources: {} validation: openAPIV3Schema: diff --git a/pkg/appfile/addon.go b/pkg/appfile/addon.go index b53e4f061..d0f1f48e9 100644 --- a/pkg/appfile/addon.go +++ b/pkg/appfile/addon.go @@ -34,7 +34,8 @@ func ApplyTerraform(app *v1alpha2.Application, k8sClient client.Client, ioStream var nativeVelaComponents []v1alpha2.ApplicationComponent // parse template appParser := NewApplicationParser(k8sClient, dm) - appFile, err := appParser.GenerateAppFile(app.Name, app) + // TODO(wangyike) this context only for compiling success, lately mabey surport setting sysNs and appNs in api-server or cli + appFile, err := appParser.GenerateAppFile(context.TODO(), app.Name, app) if err != nil { return nil, fmt.Errorf("failed to parse appfile: %w", err) } diff --git a/pkg/appfile/parser.go b/pkg/appfile/parser.go index c872dc97f..f88253cd9 100644 --- a/pkg/appfile/parser.go +++ b/pkg/appfile/parser.go @@ -1,6 +1,8 @@ package appfile import ( + "context" + "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" "github.com/pkg/errors" kerrors "k8s.io/apimachinery/pkg/api/errors" @@ -130,12 +132,12 @@ func NewApplicationParser(cli client.Client, dm discoverymapper.DiscoveryMapper) } // GenerateAppFile converts an application to an Appfile -func (p *Parser) GenerateAppFile(name string, app *v1alpha2.Application) (*Appfile, error) { +func (p *Parser) GenerateAppFile(ctx context.Context, name string, app *v1alpha2.Application) (*Appfile, error) { appfile := new(Appfile) appfile.Name = name var wds []*Workload for _, comp := range app.Spec.Components { - wd, err := p.parseWorkload(comp) + wd, err := p.parseWorkload(ctx, comp) if err != nil { return nil, err } @@ -146,12 +148,12 @@ func (p *Parser) GenerateAppFile(name string, app *v1alpha2.Application) (*Appfi return appfile, nil } -func (p *Parser) parseWorkload(comp v1alpha2.ApplicationComponent) (*Workload, error) { +func (p *Parser) parseWorkload(ctx context.Context, comp v1alpha2.ApplicationComponent) (*Workload, error) { workload := new(Workload) workload.Traits = []*Trait{} workload.Name = comp.Name workload.Type = comp.WorkloadType - templ, err := util.LoadTemplate(p.client, workload.Type, types.TypeWorkload) + templ, err := util.LoadTemplate(ctx, p.client, workload.Type, types.TypeWorkload) if err != nil && !kerrors.IsNotFound(err) { return nil, errors.WithMessagef(err, "fetch type of %s", comp.Name) } @@ -169,7 +171,7 @@ func (p *Parser) parseWorkload(comp v1alpha2.ApplicationComponent) (*Workload, e if err != nil { return nil, errors.Errorf("fail to parse properties of %s for %s", traitValue.Name, comp.Name) } - trait, err := p.parseTrait(traitValue.Name, properties) + trait, err := p.parseTrait(ctx, traitValue.Name, properties) if err != nil { return nil, errors.WithMessagef(err, "component(%s) parse trait(%s)", comp.Name, traitValue.Name) } @@ -177,7 +179,7 @@ func (p *Parser) parseWorkload(comp v1alpha2.ApplicationComponent) (*Workload, e workload.Traits = append(workload.Traits, trait) } for scopeType, instanceName := range comp.Scopes { - gvk, err := util.GetScopeGVK(p.client, p.dm, scopeType) + gvk, err := util.GetScopeGVK(ctx, p.client, p.dm, scopeType) if err != nil { return nil, err } @@ -189,8 +191,8 @@ func (p *Parser) parseWorkload(comp v1alpha2.ApplicationComponent) (*Workload, e return workload, nil } -func (p *Parser) parseTrait(name string, properties map[string]interface{}) (*Trait, error) { - templ, err := util.LoadTemplate(p.client, name, types.TypeTrait) +func (p *Parser) parseTrait(ctx context.Context, name string, properties map[string]interface{}) (*Trait, error) { + templ, err := util.LoadTemplate(ctx, p.client, name, types.TypeTrait) if kerrors.IsNotFound(err) { return nil, errors.Errorf("trait definition of %s not found", name) } diff --git a/pkg/appfile/parser_test.go b/pkg/appfile/parser_test.go index 6326e9b8b..cf5c624a8 100644 --- a/pkg/appfile/parser_test.go +++ b/pkg/appfile/parser_test.go @@ -239,7 +239,7 @@ var _ = Describe("Test application parser", func() { }, } - appfile, err := NewApplicationParser(&tclient, nil).GenerateAppFile("test", &o) + appfile, err := NewApplicationParser(&tclient, nil).GenerateAppFile(context.TODO(), "test", &o) Expect(err).ShouldNot(HaveOccurred()) Expect(equal(expectedExceptApp, appfile)).Should(BeTrue()) diff --git a/pkg/commands/dryrun.go b/pkg/commands/dryrun.go index 012450acc..884f3af44 100644 --- a/pkg/commands/dryrun.go +++ b/pkg/commands/dryrun.go @@ -1,6 +1,7 @@ package commands import ( + "context" "encoding/json" "io/ioutil" "path/filepath" @@ -15,6 +16,7 @@ import ( "github.com/oam-dev/kubevela/pkg/appfile" cmdutil "github.com/oam-dev/kubevela/pkg/commands/util" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" + oamutil "github.com/oam-dev/kubevela/pkg/oam/util" ) type dryRunOptions struct { @@ -52,7 +54,8 @@ func NewDryRunCommand(c types.Args, ioStreams cmdutil.IOStreams) *cobra.Command parser := appfile.NewApplicationParser(newClient, dm) - appFile, err := parser.GenerateAppFile(app.Name, app) + ctx := oamutil.SetNnamespaceInCtx(context.Background(), app.Namespace) + appFile, err := parser.GenerateAppFile(ctx, app.Name, app) if err != nil { return errors.WithMessage(err, "generate appFile") } diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go index 3792118fc..74ff4f28a 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller.go @@ -37,6 +37,7 @@ import ( core "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" + oamutil "github.com/oam-dev/kubevela/pkg/oam/util" ) // RolloutReconcileWaitTime is the time to wait before reconcile again an application still in rollout phase @@ -93,7 +94,9 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { // parse template appParser := appfile.NewApplicationParser(r.Client, r.dm) - appfile, err := appParser.GenerateAppFile(app.Name, app) + ctx = oamutil.SetNnamespaceInCtx(ctx, app.Namespace) + + appfile, err := appParser.GenerateAppFile(ctx, app.Name, app) if err != nil { handler.l.Error(err, "[Handle Parse]") app.Status.SetConditions(errorCondition("Parsed", err)) diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go index 02a9fad42..f67850253 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/application_controller_test.go @@ -651,7 +651,7 @@ var _ = Describe("Test Application Controller", func() { ntd, otd := &v1alpha2.TraitDefinition{}, &v1alpha2.TraitDefinition{} tDDefJson, _ := yaml.YAMLToJSON([]byte(tdDefYamlWithHttp)) Expect(json.Unmarshal(tDDefJson, ntd)).Should(BeNil()) - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: "scaler"}, otd)).Should(BeNil()) + Expect(k8sClient.Get(ctx, client.ObjectKey{Name: ntd.Name, Namespace: ntd.Namespace}, otd)).Should(BeNil()) ntd.ResourceVersion = otd.ResourceVersion Expect(k8sClient.Update(ctx, ntd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) @@ -695,13 +695,13 @@ var _ = Describe("Test Application Controller", func() { nwd, owd := &v1alpha2.WorkloadDefinition{}, &v1alpha2.WorkloadDefinition{} wDDefJson, _ := yaml.YAMLToJSON([]byte(wDDefWithHealthYaml)) Expect(json.Unmarshal(wDDefJson, nwd)).Should(BeNil()) - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: "worker"}, owd)).Should(BeNil()) + Expect(k8sClient.Get(ctx, client.ObjectKey{Name: nwd.Name, Namespace: nwd.Namespace}, owd)).Should(BeNil()) nwd.ResourceVersion = owd.ResourceVersion Expect(k8sClient.Update(ctx, nwd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) ntd, otd := &v1alpha2.TraitDefinition{}, &v1alpha2.TraitDefinition{} tDDefJson, _ := yaml.YAMLToJSON([]byte(tDDefWithHealthYaml)) Expect(json.Unmarshal(tDDefJson, ntd)).Should(BeNil()) - Expect(k8sClient.Get(ctx, client.ObjectKey{Name: "scaler"}, otd)).Should(BeNil()) + Expect(k8sClient.Get(ctx, client.ObjectKey{Name: ntd.Name, Namespace: ntd.Namespace}, otd)).Should(BeNil()) ntd.ResourceVersion = otd.ResourceVersion Expect(k8sClient.Update(ctx, ntd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) compName := "myweb-health" @@ -995,7 +995,7 @@ const ( kind: ScopeDefinition metadata: name: healthscopes.core.oam.dev - namespace: default + namespace: vela-system spec: workloadRefsPath: spec.workloadRefs allowComponentOverlap: true @@ -1007,6 +1007,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: worker + namespace: vela-system annotations: definition.oam.dev/description: "Long-running scalable backend worker without network endpoint" spec: @@ -1066,6 +1067,7 @@ spec: kind: WorkloadDefinition metadata: name: webserver + namespace: vela-system annotations: definition.oam.dev/description: "webserver was composed by deployment and service" spec: @@ -1157,6 +1159,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: worker + namespace: vela-system annotations: definition.oam.dev/description: "Long-running scalable backend worker without network endpoint" spec: @@ -1217,6 +1220,7 @@ spec: kind: WorkloadDefinition metadata: name: nworker + namespace: vela-system annotations: definition.oam.dev/description: "Describes long-running, scalable, containerized services that running at backend. They do NOT have network endpoint to receive external network traffic." spec: @@ -1286,6 +1290,7 @@ metadata: annotations: definition.oam.dev/description: "Manually scale the app" name: scaler + namespace: vela-system spec: appliesToWorkloads: - webservice @@ -1315,6 +1320,7 @@ metadata: annotations: definition.oam.dev/description: "Manually scale the app" name: scaler + namespace: vela-system spec: appliesToWorkloads: - webservice @@ -1359,6 +1365,7 @@ metadata: annotations: definition.oam.dev/description: "Manually scale the app" name: scaler + namespace: vela-system spec: appliesToWorkloads: - webservice @@ -1387,6 +1394,7 @@ spec: kind: TraitDefinition metadata: name: ingress + namespace: vela-system spec: status: customStatus: |- diff --git a/pkg/controller/core.oam.dev/v1alpha2/application/suite_test.go b/pkg/controller/core.oam.dev/v1alpha2/application/suite_test.go index 3fce396c3..7791644b7 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/application/suite_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/application/suite_test.go @@ -17,12 +17,16 @@ limitations under the License. package application import ( + "context" + "os" "path/filepath" "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" @@ -61,9 +65,16 @@ var _ = BeforeSuite(func(done Done) { logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) By("bootstrapping test environment") + var yamlPath string + if _, set := os.LookupEnv("COMPATIBILITY_TEST"); set { + yamlPath = "../../../../../test/compatibility-test/testdata" + } else { + yamlPath = filepath.Join("../../../../..", "charts", "vela-core", "crds") + } + logf.Log.Info("start application suit test", "yaml_path", yamlPath) testEnv = &envtest.Environment{ UseExistingCluster: pointer.BoolPtr(false), - CRDDirectoryPaths: []string{filepath.Join("../../../../..", "charts", "vela-core", "crds")}, + CRDDirectoryPaths: []string{yamlPath}, } var err error @@ -89,6 +100,8 @@ var _ = BeforeSuite(func(done Done) { Scheme: testScheme, dm: dm, } + definitonNs := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "vela-system"}} + Expect(k8sClient.Create(context.Background(), definitonNs.DeepCopy())).Should(BeNil()) close(done) }, 60) diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/applicationconfiguration.go b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/applicationconfiguration.go index 176d4161b..9bdce550f 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/applicationconfiguration.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/applicationconfiguration.go @@ -230,6 +230,7 @@ func (r *OAMApplicationReconciler) Reconcile(req reconcile.Request) (result reco } acPatch := ac.DeepCopy() + ctx = util.SetNnamespaceInCtx(ctx, ac.Namespace) if ac.ObjectMeta.DeletionTimestamp.IsZero() { if registerFinalizers(ac) { log.Debug("Register new finalizers", "finalizers", ac.ObjectMeta.Finalizers) diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/apply_test.go b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/apply_test.go index df786cd70..07a7a6cce 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/apply_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/apply_test.go @@ -126,9 +126,8 @@ func TestApplyWorkloads(t *testing.T) { } type args struct { - ctx context.Context - ws []v1alpha2.WorkloadStatus - w []Workload + ws []v1alpha2.WorkloadStatus + w []Workload } cases := map[string]struct { @@ -330,7 +329,7 @@ func TestApplyWorkloads(t *testing.T) { t.Run(name, func(t *testing.T) { mapper := mock.NewMockDiscoveryMapper() w := workloads{applicator: tc.applicator, rawClient: tc.rawClient, dm: mapper} - err := w.Apply(tc.args.ctx, tc.args.ws, tc.args.w) + err := w.Apply(context.TODO(), tc.args.ws, tc.args.w) if diff := cmp.Diff(tc.want, err, test.EquateErrors()); diff != "" { t.Errorf("\n%s\nw.Apply(...): -want error, +got error:\n%s", tc.reason, diff) diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/apply_trait_test.go b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/apply_trait_test.go index b19cfd65e..b1a319e1e 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/apply_trait_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/apply_trait_test.go @@ -149,7 +149,8 @@ var _ = Describe("Test apply changes to trait", func() { APIVersion: "TraitDefinition", }, ObjectMeta: metav1.ObjectMeta{ - Name: "bars.example.com", + Name: "bars.example.com", + Namespace: "vela-system", }, Spec: v1alpha2.TraitDefinitionSpec{ Reference: v1alpha2.DefinitionReference{ diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/render_test.go b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/render_test.go index f9e38aff4..1145da372 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/render_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/render_test.go @@ -39,7 +39,6 @@ import ( core "github.com/oam-dev/kubevela/apis/core.oam.dev" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" - "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/mock" "github.com/oam-dev/kubevela/pkg/oam/util" @@ -99,8 +98,7 @@ func TestRenderComponents(t *testing.T) { trait ResourceRenderer } type args struct { - ctx context.Context - ac *v1alpha2.ApplicationConfiguration + ac *v1alpha2.ApplicationConfiguration } type want struct { w []Workload @@ -525,7 +523,7 @@ func TestRenderComponents(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { r := &components{tc.fields.client, mock.NewMockDiscoveryMapper(), tc.fields.params, tc.fields.workload, tc.fields.trait} - got, _, err := r.Render(tc.args.ctx, tc.args.ac) + got, _, err := r.Render(context.TODO(), tc.args.ac) if diff := cmp.Diff(tc.want.err, err, test.EquateErrors()); diff != "" { t.Errorf("\n%s\nr.Render(...): -want error, +got error:\n%s\n", tc.reason, diff) } @@ -813,8 +811,7 @@ func TestRenderTraitWithoutMetadataName(t *testing.T) { trait ResourceRenderer } type args struct { - ctx context.Context - ac *v1alpha2.ApplicationConfiguration + ac *v1alpha2.ApplicationConfiguration } type want struct { w []Workload @@ -871,7 +868,7 @@ func TestRenderTraitWithoutMetadataName(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { r := &components{tc.fields.client, mock.NewMockDiscoveryMapper(), tc.fields.params, tc.fields.workload, tc.fields.trait} - got, _, _ := r.Render(tc.args.ctx, tc.args.ac) + got, _, _ := r.Render(context.TODO(), tc.args.ac) if len(got) == 0 || len(got[0].Traits) == 0 || got[0].Traits[0].Object.GetName() != util.GenTraitName(componentName, ac.Spec.Components[0].Traits[0].DeepCopy(), "") { t.Errorf("\n%s\nr.Render(...): -want error, +got error:\n%s\n", tc.reason, "Trait name is NOT "+ "automatically set.") diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/suite_test.go b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/suite_test.go index 029aca2a2..3108b83d2 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/suite_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationconfiguration/suite_test.go @@ -2,6 +2,7 @@ package applicationconfiguration import ( "context" + "os" "path/filepath" "testing" "time" @@ -10,6 +11,7 @@ import ( . "github.com/onsi/gomega" "github.com/crossplane/crossplane-runtime/pkg/logging" + corev1 "k8s.io/api/core/v1" crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -55,9 +57,16 @@ func TestReconcilerSuit(t *testing.T) { var _ = BeforeSuite(func(done Done) { ctx := context.Background() By("Bootstrapping test environment") + var yamlPath string + if _, set := os.LookupEnv("COMPATIBILITY_TEST"); set { + yamlPath = "../../../../../test/compatibility-test/testdata" + } else { + yamlPath = filepath.Join("../../../../..", "charts", "vela-core", "crds") + } + logf.Log.Info("start applicationconfiguration suit test", "yaml_path", yamlPath) testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{ - filepath.Join("../../../../..", "charts/vela-core/crds"), // this has all the required CRDs, + yamlPath, // this has all the required CRDs, }, } var err error @@ -156,7 +165,8 @@ var _ = BeforeSuite(func(done Done) { By("Creating workload definition and trait definition") wd := v1alpha2.WorkloadDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "foo.example.com", + Name: "foo.example.com", + Namespace: "vela-system", }, Spec: v1alpha2.WorkloadDefinitionSpec{ Reference: v1alpha2.DefinitionReference{ @@ -166,7 +176,8 @@ var _ = BeforeSuite(func(done Done) { } td := v1alpha2.TraitDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "foo.example.com", + Name: "foo.example.com", + Namespace: "vela-system", }, Spec: v1alpha2.TraitDefinitionSpec{ Reference: v1alpha2.DefinitionReference{ @@ -177,7 +188,8 @@ var _ = BeforeSuite(func(done Done) { rollout := v1alpha2.TraitDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "rollout-revision", + Name: "rollout-revision", + Namespace: "vela-system", }, Spec: v1alpha2.TraitDefinitionSpec{ Reference: v1alpha2.DefinitionReference{ @@ -186,6 +198,8 @@ var _ = BeforeSuite(func(done Done) { RevisionEnabled: true, }, } + definitonNs := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "vela-system"}} + Expect(k8sClient.Create(context.Background(), definitonNs.DeepCopy())).Should(BeNil()) // For some reason, WorkloadDefinition is created as a Cluster scope object Expect(k8sClient.Create(ctx, &wd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/application-workload.go b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/application-workload.go index 5a8c2a7bd..bb4312ad5 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/application-workload.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/application-workload.go @@ -31,7 +31,8 @@ func (r *Reconciler) extractWorkloadTypeAndGVK(ctx context.Context, componentLis } // get the workload definition // the validator webhook has checked that source and the target are the same type - wd, err := oamutil.GetWorkloadDefinition(ctx, r, componentType) + wd := new(corev1alpha2.WorkloadDefinition) + err := oamutil.GetDefinition(ctx, r, wd, componentType) if err != nil { return "", nil, errors.Wrap(err, fmt.Sprintf("failed to get workload definition %s", componentType)) } diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go index 68b4efd9d..335c2fe4f 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/applicationdeployment_controller.go @@ -22,6 +22,7 @@ import ( "github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/application" "github.com/oam-dev/kubevela/pkg/oam" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" + oamutil "github.com/oam-dev/kubevela/pkg/oam/util" ) const appDeployFinalizer = "finalizers.applicationdeployment.oam.dev" @@ -71,6 +72,8 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (res reconcile.Result, retErr e // TODO: check if the target/source has changed r.handleFinalizer(&appDeploy) + ctx = oamutil.SetNnamespaceInCtx(ctx, appDeploy.Namespace) + // Get the target application var targetApp corev1alpha2.Application var sourceApp *corev1alpha2.Application diff --git a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/suite_test.go b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/suite_test.go index ecdfd034e..dd3364696 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/suite_test.go +++ b/pkg/controller/core.oam.dev/v1alpha2/applicationdeployment/suite_test.go @@ -1,6 +1,7 @@ package applicationdeployment import ( + "os" "path/filepath" "testing" @@ -37,9 +38,16 @@ var _ = BeforeSuite(func(done Done) { logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) By("bootstrapping test environment") + var yamlPath string + if _, set := os.LookupEnv("COMPATIBILITY_TEST"); set { + yamlPath = "../../../../../test/compatibility-test/testdata" + } else { + yamlPath = filepath.Join("../../../../..", "charts", "vela-core", "crds") + } + logf.Log.Info("start application deployment suit test", "yaml_path", yamlPath) testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{ - filepath.Join("../../../..", "charts/vela-core/crds"), // this has all the required CRDs, + yamlPath, // this has all the required CRDs, filepath.Join("..", "config", "crd", "bases")}, } diff --git a/pkg/controller/core.oam.dev/v1alpha2/core/traits/manualscalertrait/manualscalertrait_controller.go b/pkg/controller/core.oam.dev/v1alpha2/core/traits/manualscalertrait/manualscalertrait_controller.go index 6853c9c9b..893dbc558 100644 --- a/pkg/controller/core.oam.dev/v1alpha2/core/traits/manualscalertrait/manualscalertrait_controller.go +++ b/pkg/controller/core.oam.dev/v1alpha2/core/traits/manualscalertrait/manualscalertrait_controller.go @@ -94,6 +94,9 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { if err := r.Get(ctx, req.NamespacedName, &manualScalar); err != nil { return ctrl.Result{}, client.IgnoreNotFound(err) } + + ctx = util.SetNnamespaceInCtx(ctx, manualScalar.Namespace) + r.log.Info("Get the manualscalar trait", "ReplicaCount", manualScalar.Spec.ReplicaCount, "Annotations", manualScalar.GetAnnotations()) // find the resource object to record the event to, default is the parent appConfig. diff --git a/pkg/controller/standard.oam.dev/v1alpha1/autoscaler/autoscaler_controller.go b/pkg/controller/standard.oam.dev/v1alpha1/autoscaler/autoscaler_controller.go index fdae3611a..82e9feb56 100644 --- a/pkg/controller/standard.oam.dev/v1alpha1/autoscaler/autoscaler_controller.go +++ b/pkg/controller/standard.oam.dev/v1alpha1/autoscaler/autoscaler_controller.go @@ -73,6 +73,8 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { } log.Info("Retrieved trait Autoscaler", "APIVersion", scaler.APIVersion, "Kind", scaler.Kind) + ctx = util.SetNnamespaceInCtx(ctx, scaler.Namespace) + // find the resource object to record the event to, default is the parent appConfig. eventObj, err := util.LocateParentAppConfig(ctx, r.Client, &scaler) if err != nil { diff --git a/pkg/controller/standard.oam.dev/v1alpha1/metrics/metricstrait_controller.go b/pkg/controller/standard.oam.dev/v1alpha1/metrics/metricstrait_controller.go index 2779a3e1b..c68dd7d17 100644 --- a/pkg/controller/standard.oam.dev/v1alpha1/metrics/metricstrait_controller.go +++ b/pkg/controller/standard.oam.dev/v1alpha1/metrics/metricstrait_controller.go @@ -103,6 +103,8 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { "workload reference", metricsTrait.Spec.WorkloadReference, "labels", metricsTrait.GetLabels()) + ctx = oamutil.SetNnamespaceInCtx(ctx, metricsTrait.Namespace) + // find the resource object to record the event to, default is the parent appConfig. eventObj, err := oamutil.LocateParentAppConfig(ctx, r.Client, &metricsTrait) if eventObj == nil { diff --git a/pkg/controller/standard.oam.dev/v1alpha1/metrics/suite_test.go b/pkg/controller/standard.oam.dev/v1alpha1/metrics/suite_test.go index f57e9b881..6a85fed7b 100644 --- a/pkg/controller/standard.oam.dev/v1alpha1/metrics/suite_test.go +++ b/pkg/controller/standard.oam.dev/v1alpha1/metrics/suite_test.go @@ -18,6 +18,7 @@ package metrics import ( "context" + "os" "path/filepath" "testing" @@ -68,10 +69,18 @@ var _ = BeforeSuite(func(done Done) { }, } By("Bootstrapping test environment") + var yamlPath string + if _, set := os.LookupEnv("COMPATIBILITY_TEST"); set { + yamlPath = "../../../../../test/compatibility-test/testdata" + } else { + yamlPath = filepath.Join("../../../../..", "charts", "vela-core", "crds") + } + logf.Log.Info("start metrics test", "yaml_path", yamlPath) useExistCluster := false testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{ - filepath.Join("../../../../..", "charts/vela-core/crds"), // this has all the required CRDs, + yamlPath, // this has all the required oam CRDs, + filepath.Join("..", "testdata/crds"), }, UseExistingCluster: &useExistCluster, } diff --git a/pkg/controller/standard.oam.dev/v1alpha1/routes/route_controller.go b/pkg/controller/standard.oam.dev/v1alpha1/routes/route_controller.go index ec343d6e9..95c2d9fcf 100644 --- a/pkg/controller/standard.oam.dev/v1alpha1/routes/route_controller.go +++ b/pkg/controller/standard.oam.dev/v1alpha1/routes/route_controller.go @@ -82,6 +82,8 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { "workload reference", routeTrait.Spec.WorkloadReference, "labels", routeTrait.GetLabels()) + ctx = oamutil.SetNnamespaceInCtx(ctx, routeTrait.Namespace) + // find the resource object to record the event to, default is the parent appConfig. eventObj, err := oamutil.LocateParentAppConfig(ctx, r.Client, &routeTrait) if eventObj == nil { diff --git a/pkg/controller/standard.oam.dev/v1alpha1/routes/suite_test.go b/pkg/controller/standard.oam.dev/v1alpha1/routes/suite_test.go index 4aa838ca5..e8ad3dc33 100644 --- a/pkg/controller/standard.oam.dev/v1alpha1/routes/suite_test.go +++ b/pkg/controller/standard.oam.dev/v1alpha1/routes/suite_test.go @@ -18,6 +18,7 @@ package routes import ( "context" + "os" "path/filepath" "testing" @@ -75,10 +76,18 @@ var _ = BeforeSuite(func(done Done) { }, } By("Bootstrapping test environment") + var yamlPath string + if _, set := os.LookupEnv("COMPATIBILITY_TEST"); set { + yamlPath = "../../../../../test/compatibility-test/testdata" + } else { + yamlPath = filepath.Join("../../../../..", "charts", "vela-core", "crds") + } + logf.Log.Info("start route suit_test", "yaml_path", yamlPath) useExistCluster := false testEnv = &envtest.Environment{ CRDDirectoryPaths: []string{ - filepath.Join("../../../../..", "charts/vela-core/crds"), // this has all the required CRDs, + yamlPath, // this has all the required CRDs, + filepath.Join("..", "testdata/crds"), }, UseExistingCluster: &useExistCluster, } @@ -96,6 +105,9 @@ var _ = BeforeSuite(func(done Done) { k8sClient, err = client.New(cfg, client.Options{Scheme: scheme.Scheme}) Expect(err).ToNot(HaveOccurred()) Expect(k8sClient).ToNot(BeNil()) + By("create definition namespace vela-system") + ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "vela-system"}} + Expect(k8sClient.Create(context.Background(), &ns)).Should(BeNil()) By("Starting the route trait controller in the background") mgr, err := ctrl.NewManager(cfg, ctrl.Options{ @@ -123,14 +135,14 @@ var _ = BeforeSuite(func(done Done) { Expect(k8sClient.Create(context.Background(), &routeNS)).ToNot(HaveOccurred()) routeDef := &v1alpha2.TraitDefinition{} routeDef.Name = "route" - routeDef.Namespace = RouteNSName + routeDef.Namespace = "vela-system" routeDef.Spec.Reference.Name = "routes.standard.oam.dev" routeDef.Spec.WorkloadRefPath = "spec.workloadRef" Expect(k8sClient.Create(context.Background(), routeDef)).ToNot(HaveOccurred()) webservice := &v1alpha2.WorkloadDefinition{} webservice.Name = "webservice" - webservice.Namespace = RouteNSName + webservice.Namespace = "vela-system" webservice.Spec.Reference.Name = "deployments.apps" webservice.Spec.ChildResourceKinds = []v1alpha2.ChildResourceKind{{ APIVersion: "apps/v1", @@ -143,14 +155,14 @@ var _ = BeforeSuite(func(done Done) { deployment := &v1alpha2.WorkloadDefinition{} deployment.Name = "deployment" - deployment.Namespace = RouteNSName + deployment.Namespace = "vela-system" deployment.Labels = map[string]string{"workload.oam.dev/podspecable": "true"} deployment.Spec.Reference.Name = "deployments.apps" Expect(k8sClient.Create(context.Background(), deployment)).ToNot(HaveOccurred()) deploy := &v1alpha2.WorkloadDefinition{} deploy.Name = "deploy" - deploy.Namespace = RouteNSName + deploy.Namespace = "vela-system" deploy.Spec.PodSpecPath = "spec.template.spec" deploy.Spec.Reference.Name = "deployments.apps" Expect(k8sClient.Create(context.Background(), deploy)).ToNot(HaveOccurred()) diff --git a/pkg/oam/util/helper.go b/pkg/oam/util/helper.go index 95592390d..36c63d2c8 100644 --- a/pkg/oam/util/helper.go +++ b/pkg/oam/util/helper.go @@ -72,6 +72,13 @@ const ( errFmtInvalidRevisionType = "invalid type of revision %s, type should not be %v" ) +type namespaceContextKey int + +const ( + // AppDefinitionNamespace is context key to define app namespace + AppDefinitionNamespace namespaceContextKey = iota +) + // A ConditionedObject is an Object type with condition field type ConditionedObject interface { oam.Object @@ -163,10 +170,8 @@ func FetchScopeDefinition(ctx context.Context, r client.Reader, dm discoverymapp if err != nil { return nil, err } - nn := GenNamespacedDefinitionName(spName) - // Fetch the corresponding scopeDefinition CR - scopeDefinition := &v1alpha2.ScopeDefinition{} - if err := r.Get(ctx, nn, scopeDefinition); err != nil { + scopeDefinition := new(v1alpha2.ScopeDefinition) + if err = GetDefinition(ctx, r, scopeDefinition, spName); err != nil { return nil, err } return scopeDefinition, nil @@ -180,9 +185,8 @@ func FetchTraitDefinition(ctx context.Context, r client.Reader, dm discoverymapp if err != nil { return nil, err } - // Fetch the corresponding traitDefinition CR - traitDefinition, err := GetTraitDefinition(ctx, r, trName) - if err != nil { + traitDefinition := new(v1alpha2.TraitDefinition) + if err = GetDefinition(ctx, r, traitDefinition, trName); err != nil { return nil, err } return traitDefinition, nil @@ -196,39 +200,70 @@ func FetchWorkloadDefinition(ctx context.Context, r client.Reader, dm discoverym if err != nil { return nil, err } - // Fetch the corresponding workloadDefinition CR - workloadDefinition, err := GetWorkloadDefinition(ctx, r, wldName) - if err != nil { + workloadDefinition := new(v1alpha2.WorkloadDefinition) + if err = GetDefinition(ctx, r, workloadDefinition, wldName); err != nil { return nil, err } return workloadDefinition, nil } -// GenNamespacedDefinitionName generate definition name with customized namespace -func GenNamespacedDefinitionName(dn string) types.NamespacedName { +// GetDefinitionNamespaceWithCtx will get namespace from context, it will try get `AppDefinitionNamespace` key, if not found, +// will use default system level namespace defined in `systemvar.SystemDefinitonNamespace` +func GetDefinitionNamespaceWithCtx(ctx context.Context) string { + var appNs string + if app := ctx.Value(AppDefinitionNamespace); app == nil { + appNs = oam.SystemDefinitonNamespace + } else { + appNs = app.(string) + } + return appNs +} + +// SetNnamespaceInCtx set app namespace in context, +// Sometimes webhook handler may receive request that appNs is empty string, and will cause error when search definition +// So if namespace is empty, it will use `default` namespace by default. +func SetNnamespaceInCtx(ctx context.Context, appNs string) context.Context { + if appNs == "" { + // compatible with some webhook handlers that maybe recei ve empty string as app namespace which means `default` namespace + appNs = "default" + } + ctx = context.WithValue(ctx, AppDefinitionNamespace, appNs) + return ctx +} + +// GetDefinition get definition from two level namespace +func GetDefinition(ctx context.Context, cli client.Reader, definition runtime.Object, definitionName string) error { if dns := os.Getenv(DefinitionNamespaceEnv); dns != "" { - return types.NamespacedName{Name: dn, Namespace: dns} + if err := cli.Get(ctx, types.NamespacedName{Name: definitionName, Namespace: dns}, definition); err == nil { + return nil + } else if !apierrors.IsNotFound(err) { + return err + } } - return types.NamespacedName{Name: dn} + appNs := GetDefinitionNamespaceWithCtx(ctx) + if err := cli.Get(ctx, types.NamespacedName{Name: definitionName, Namespace: appNs}, definition); err != nil { + if apierrors.IsNotFound(err) { + if err = cli.Get(ctx, types.NamespacedName{Name: definitionName, Namespace: oam.SystemDefinitonNamespace}, definition); err != nil { + if apierrors.IsNotFound(err) { + // compatibility code for old clusters those definition crd is cluster scope + var newErr error + if newErr = cli.Get(ctx, types.NamespacedName{Name: definitionName}, definition); checkRequestNamespaceError(newErr) { + return err + } + return newErr + } + return err + } + return err + } + return err + } + return nil } -// GetWorkloadDefinition Get WorkloadDefinition -func GetWorkloadDefinition(ctx context.Context, cli client.Reader, - workitemName string) (*v1alpha2.WorkloadDefinition, error) { - wd := new(v1alpha2.WorkloadDefinition) - if err := cli.Get(ctx, GenNamespacedDefinitionName(workitemName), wd); err != nil { - return nil, err - } - return wd, nil -} - -// GetTraitDefinition Get TraitDefinition -func GetTraitDefinition(ctx context.Context, cli client.Reader, traitName string) (*v1alpha2.TraitDefinition, error) { - td := new(v1alpha2.TraitDefinition) - if err := cli.Get(ctx, GenNamespacedDefinitionName(traitName), td); err != nil { - return nil, err - } - return td, nil +// when get a namespaced scope object without namespace, would get an error request namespace +func checkRequestNamespaceError(err error) bool { + return err != nil && err.Error() == "an empty namespace may not be set when a resource name is provided" } // FetchWorkloadChildResources fetch corresponding child resources given a workload diff --git a/pkg/oam/util/helper_test.go b/pkg/oam/util/helper_test.go index c20caa949..0b75a6b8b 100644 --- a/pkg/oam/util/helper_test.go +++ b/pkg/oam/util/helper_test.go @@ -15,6 +15,7 @@ import ( "github.com/pkg/errors" "github.com/stretchr/testify/assert" appsv1 "k8s.io/api/apps/v1" + apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" @@ -1330,15 +1331,6 @@ func TestGetDummy(t *testing.T) { }, util.GetDummyWorkloadDefinition(u)) } -func TestNamespacedDefinition(t *testing.T) { - ns := "namespaced" - n := "definition" - _ = os.Setenv(util.DefinitionNamespaceEnv, ns) - nn := util.GenNamespacedDefinitionName(n) - assert.Equal(t, nn.Namespace, ns) - assert.Equal(t, nn.Name, n) -} - func TestRawExtension2Map(t *testing.T) { r1 := runtime.RawExtension{ Raw: []byte(`{"a":{"c":"d"},"b":1}`), @@ -1367,3 +1359,508 @@ func TestRawExtension2Map(t *testing.T) { assert.NoError(t, err) assert.Equal(t, exp1, got2) } + +func TestGenDefinitionNsFromCtx(t *testing.T) { + type testcase struct { + ctx context.Context + wantNs string + } + testcases := []testcase{ + {ctx: context.TODO(), wantNs: "vela-system"}, + {ctx: util.SetNnamespaceInCtx(context.Background(), "vela-app"), wantNs: "vela-app"}, + {ctx: util.SetNnamespaceInCtx(context.Background(), ""), wantNs: "default"}, + } + for _, ts := range testcases { + resNs := util.GetDefinitionNamespaceWithCtx(ts.ctx) + assert.Equal(t, ts.wantNs, resNs) + + } +} + +// TestGetDefinitionError is try to mock test when get an not existed definition in namespaced scope cluster +// will get an error that tpye is not found +func TestGetDefinitionError(t *testing.T) { + ctx := context.Background() + ctx = util.SetNnamespaceInCtx(ctx, "vela-app") + + errNotFound := apierrors.NewNotFound(schema.GroupResource{Group: "core.oma.dev", Resource: "traitDefinition"}, "mock") + errNeedNamespace := fmt.Errorf("an empty namespace may not be set when a resource name is provided") + + getFunc := func(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { + ns := key.Namespace + if ns != "" { + return errNotFound + } else { + return errNeedNamespace + } + } + + client := test.MockClient{MockGet: getFunc} + td := new(v1alpha2.TraitDefinition) + got := util.GetDefinition(ctx, &client, td, "mock") + assert.Equal(t, errNotFound, got) +} + +// TestGetDefinitionWithClusterScope is try to test compatibility of GetDefinition, +// GetDefinition try to search definition in system-level namespace firstly, +// if not found will search in app namespace, still cannot find it, try to search definition without namespace +func TestGetDefinitionWithClusterScope(t *testing.T) { + ctx := context.Background() + ctx = util.SetNnamespaceInCtx(ctx, "vela-app") + // system-level definition + sys := v1alpha2.TraitDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "sysDefinition", + Namespace: "vela-system", + }, + Spec: v1alpha2.TraitDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: "definitionrefrence.core.oam.dev", + }, + }, + } + // app workload Definition + app := v1alpha2.TraitDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "appDefinition", + Namespace: "vela-app", + }, + Spec: v1alpha2.TraitDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: "definitionrefrence", + }, + }, + } + // old cluster workload trait scope definition crd is cluster scope, the namesapce field is empty + noNs := v1alpha2.TraitDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "noNsDefinition", + }, + Spec: v1alpha2.TraitDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: "definitionrefrence", + }, + }, + } + tdList := []v1alpha2.TraitDefinition{app, sys, noNs} + mockIndexer := map[string]v1alpha2.TraitDefinition{} + for i := 0; i < len(tdList); i++ { + var key string + if tdList[i].Namespace != "" { + key = tdList[i].Namespace + "/" + tdList[i].Name + } else { + key = tdList[i].Name + } + mockIndexer[key] = tdList[i] + } + + getFunc := func(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { + var namespacedName string + if key.Namespace != "" { + namespacedName = key.Namespace + "/" + key.Name + } else { + namespacedName = key.Name + } + td, ok := mockIndexer[namespacedName] + if ok { + obj, _ := obj.(*v1alpha2.TraitDefinition) + *obj = td + return nil + } else { + return apierrors.NewNotFound(schema.GroupResource{Group: "core.oma.dev", Resource: "traitDefinition"}, namespacedName) + } + } + + type want struct { + td *v1alpha2.TraitDefinition + err error + } + testcases := map[string]struct { + tdName string + want want + }{ + "app namespace is first level": { + tdName: "appDefinition", + want: want{ + err: nil, + td: &app, + }, + }, + "got sys namespace in system levle": { + tdName: "sysDefinition", + want: want{ + err: nil, + td: &sys, + }, + }, + "old cluster traitdefinition crd is cluster scope": { + tdName: "noNsDefinition", + want: want{ + err: nil, + td: &noNs, + }, + }, + "return err search not exsited definition": { + tdName: "notExistedDefinition", + want: want{ + err: apierrors.NewNotFound(schema.GroupResource{Group: "core.oma.dev", Resource: "traitDefinition"}, "notExistedDefinition"), + td: new(v1alpha2.TraitDefinition), + }, + }, + } + + tclient := test.MockClient{MockGet: getFunc} + + for name, tc := range testcases { + got := new(v1alpha2.TraitDefinition) + err := util.GetDefinition(ctx, &tclient, got, tc.tdName) + t.Log(fmt.Sprint("Running test: ", name)) + + assert.Equal(t, tc.want.err, err) + assert.Equal(t, tc.want.td, got) + } +} + +func TestGetWorkloadDefinition(t *testing.T) { + // Test common variables + ctx := context.Background() + ctx = util.SetNnamespaceInCtx(ctx, "vela-app") + + // sys workload Definition + sysWorkloadDefinition := v1alpha2.WorkloadDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mockdefinition", + Namespace: "vela-system", + }, + Spec: v1alpha2.WorkloadDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: "definitionrefrence.core.oam.dev", + }, + }, + } + + // app workload Definition + appWorkloadDefinition := v1alpha2.WorkloadDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mockdefinition.core.oam.dev", + Namespace: "vela-app", + }, + Spec: v1alpha2.WorkloadDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: "definitionrefrence.core.oam.dev", + }, + }, + } + + type fields struct { + getFunc test.MockGetFn + } + type want struct { + wld v1alpha2.WorkloadDefinition + err error + } + + cases := map[string]struct { + fields fields + want want + }{ + + "app defintion will overlay system definition": { + fields: fields{ + getFunc: func(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { + o := obj.(*v1alpha2.WorkloadDefinition) + if key.Namespace == "vela-system" { + *o = sysWorkloadDefinition + } else { + *o = appWorkloadDefinition + } + return nil + }, + }, + want: want{ + wld: appWorkloadDefinition, + err: nil, + }, + }, + + "return system definiton when cannot find in app ns": { + fields: fields{ + getFunc: func(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { + if key.Namespace == "vela-system" { + o := obj.(*v1alpha2.WorkloadDefinition) + *o = sysWorkloadDefinition + return nil + } + return apierrors.NewNotFound(schema.GroupResource{Group: "core.oma.dev", Resource: "workloadDefinition"}, key.Name) + }, + }, + want: want{ + wld: sysWorkloadDefinition, + err: nil, + }, + }, + } + for name, tc := range cases { + tclient := test.MockClient{ + MockGet: tc.fields.getFunc, + } + got := new(v1alpha2.WorkloadDefinition) + err := util.GetDefinition(ctx, &tclient, got, "mockdefinition") + t.Log(fmt.Sprint("Running test: ", name)) + + assert.Equal(t, tc.want.err, err) + assert.Equal(t, tc.want.wld, *got) + } +} + +func TestGetTraitDefinition(t *testing.T) { + // Test common variables + ctx := context.Background() + ctx = util.SetNnamespaceInCtx(ctx, "vela-app") + + // sys workload Definition + sysTraitDefinition := v1alpha2.TraitDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mockdefinition", + Namespace: "vela-system", + }, + Spec: v1alpha2.TraitDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: "definitionrefrence.core.oam.dev", + }, + }, + } + + // app workload Definition + appTraitDefinition := v1alpha2.TraitDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mockdefinition.core.oam.dev", + Namespace: "vela-app", + }, + Spec: v1alpha2.TraitDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: "definitionrefrence.core.oam.dev", + }, + }, + } + + type fields struct { + getFunc test.MockGetFn + } + type want struct { + wld v1alpha2.TraitDefinition + err error + } + + cases := map[string]struct { + fields fields + want want + }{ + "app defintion will overlay system definition": { + fields: fields{ + getFunc: func(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { + o := obj.(*v1alpha2.TraitDefinition) + if key.Namespace == "vela-system" { + *o = sysTraitDefinition + } else { + *o = appTraitDefinition + } + return nil + }, + }, + want: want{ + wld: appTraitDefinition, + err: nil, + }, + }, + + "return system definiton when cannot find in app ns": { + fields: fields{ + getFunc: func(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { + if key.Namespace == "vela-system" { + o := obj.(*v1alpha2.TraitDefinition) + *o = sysTraitDefinition + return nil + } + return apierrors.NewNotFound(schema.GroupResource{Group: "core.oma.dev", Resource: "workloadDefinition"}, key.Name) + }, + }, + want: want{ + wld: sysTraitDefinition, + err: nil, + }, + }, + } + for name, tc := range cases { + tclient := test.MockClient{ + MockGet: tc.fields.getFunc, + } + got := new(v1alpha2.TraitDefinition) + err := util.GetDefinition(ctx, &tclient, got, "mockdefinition") + t.Log(fmt.Sprint("Running test: ", name)) + + assert.Equal(t, tc.want.err, err) + assert.Equal(t, tc.want.wld, *got) + } +} + +func TestGetDefinition(t *testing.T) { + // Test common variables + env := "env-namespace" + + // sys workload Definition + sysTraitDefinition := v1alpha2.TraitDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mockdefinition", + Namespace: "vela-system", + }, + } + + // app workload Definition + appTraitDefinition := v1alpha2.TraitDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mockdefinition", + Namespace: "vela-app", + }, + } + + // env workload Definition + envTraitDefinition := v1alpha2.TraitDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "mockdefinition", + Namespace: env, + }, + } + + cli := test.MockClient{MockGet: func(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { + o := obj.(*v1alpha2.TraitDefinition) + switch key.Namespace { + case "vela-system": + *o = sysTraitDefinition + case "vela-app": + *o = appTraitDefinition + case env: + *o = envTraitDefinition + default: + return apierrors.NewNotFound(schema.GroupResource{Group: "core.oma.dev", Resource: "traitDefinition"}, key.Name) + } + return nil + }} + + ctx := context.Background() + ctx = util.SetNnamespaceInCtx(ctx, "vela-app") + appTd := new(v1alpha2.TraitDefinition) + err := util.GetDefinition(ctx, &cli, appTd, "mockTrait") + assert.Equal(t, nil, err) + assert.Equal(t, &appTraitDefinition, appTd) + + err = os.Setenv(util.DefinitionNamespaceEnv, env) + assert.Equal(t, nil, err) + envTd := new(v1alpha2.TraitDefinition) + err = util.GetDefinition(ctx, &cli, envTd, "mockTrait") + assert.Equal(t, nil, err) + assert.Equal(t, &envTraitDefinition, envTd) +} + +func TestGetScopeDefiniton(t *testing.T) { + ctx := context.Background() + namespace := "vela-app" + ctx = util.SetNnamespaceInCtx(ctx, namespace) + scopeDefinitionKind := "ScopeDefinition" + mockVerision := "core.oam.dev/v1alpha2" + scopeDefinitionName := "mockscopes.core.oam.dev" + scopeDefinitionRefName := "mockscopes.core.oam.dev" + scopeDefinitionWorkloadRefsPath := "spec.workloadRefs" + + sysScopeDefinition := v1alpha2.ScopeDefinition{ + TypeMeta: metav1.TypeMeta{ + Kind: scopeDefinitionKind, + APIVersion: mockVerision, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: scopeDefinitionName, + Namespace: "vela-system", + }, + Spec: v1alpha2.ScopeDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: scopeDefinitionRefName, + }, + WorkloadRefsPath: scopeDefinitionWorkloadRefsPath, + AllowComponentOverlap: false, + }, + } + + appScopeDefinition := v1alpha2.ScopeDefinition{ + TypeMeta: metav1.TypeMeta{ + Kind: scopeDefinitionKind, + APIVersion: mockVerision, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: scopeDefinitionName, + Namespace: namespace, + }, + Spec: v1alpha2.ScopeDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: scopeDefinitionRefName, + }, + WorkloadRefsPath: scopeDefinitionWorkloadRefsPath, + AllowComponentOverlap: false, + }, + } + type fields struct { + getFunc test.MockGetFn + } + type want struct { + spd *v1alpha2.ScopeDefinition + err error + } + cases := map[string]struct { + fields fields + want want + }{ + "app defintion will overlay system definition": { + fields: fields{ + getFunc: func(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { + o := obj.(*v1alpha2.ScopeDefinition) + if key.Namespace == "vela-system" { + *o = sysScopeDefinition + } else { + *o = appScopeDefinition + } + return nil + }, + }, + want: want{ + spd: &appScopeDefinition, + err: nil, + }, + }, + + "return system definiton when cannot find in app ns": { + fields: fields{ + getFunc: func(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { + if key.Namespace == "vela-system" { + o := obj.(*v1alpha2.ScopeDefinition) + *o = sysScopeDefinition + return nil + } + return apierrors.NewNotFound(schema.GroupResource{Group: "core.oma.dev", Resource: "scopeDefinition"}, key.Name) + }, + }, + want: want{ + spd: &sysScopeDefinition, + err: nil, + }, + }, + } + for name, tc := range cases { + tclient := test.MockClient{ + MockGet: tc.fields.getFunc, + } + got := new(v1alpha2.ScopeDefinition) + err := util.GetDefinition(ctx, &tclient, got, "mockdefinition") + t.Log(fmt.Sprint("Running test: ", name)) + assert.Equal(t, tc.want.err, err) + assert.Equal(t, tc.want.spd, got) + } +} diff --git a/pkg/oam/util/template.go b/pkg/oam/util/template.go index 6d16e7e00..c66677c33 100644 --- a/pkg/oam/util/template.go +++ b/pkg/oam/util/template.go @@ -24,23 +24,24 @@ type Template struct { } // GetScopeGVK Get ScopeDefinition -func GetScopeGVK(cli client.Client, dm discoverymapper.DiscoveryMapper, +func GetScopeGVK(ctx context.Context, cli client.Reader, dm discoverymapper.DiscoveryMapper, name string) (schema.GroupVersionKind, error) { var gvk schema.GroupVersionKind sd := new(v1alpha2.ScopeDefinition) - if err := cli.Get(context.Background(), client.ObjectKey{ - Name: name, - }, sd); err != nil { + err := GetDefinition(ctx, cli, sd, name) + if err != nil { return gvk, err } + return GetGVKFromDefinition(dm, sd.Spec.Reference) } // LoadTemplate Get template according to key -func LoadTemplate(cli client.Reader, key string, kd types.CapType) (*Template, error) { +func LoadTemplate(ctx context.Context, cli client.Reader, key string, kd types.CapType) (*Template, error) { switch kd { case types.TypeWorkload: - wd, err := GetWorkloadDefinition(context.TODO(), cli, key) + wd := new(v1alpha2.WorkloadDefinition) + err := GetDefinition(ctx, cli, wd, key) if err != nil { return nil, errors.WithMessagef(err, "LoadTemplate [%s] ", key) } @@ -59,7 +60,8 @@ func LoadTemplate(cli client.Reader, key string, kd types.CapType) (*Template, e return tmpl, nil case types.TypeTrait: - td, err := GetTraitDefinition(context.TODO(), cli, key) + td := new(v1alpha2.TraitDefinition) + err := GetDefinition(ctx, cli, td, key) if err != nil { return nil, errors.WithMessagef(err, "LoadTemplate [%s] ", key) } diff --git a/pkg/oam/util/template_test.go b/pkg/oam/util/template_test.go index a667f2313..63257f4cd 100644 --- a/pkg/oam/util/template_test.go +++ b/pkg/oam/util/template_test.go @@ -65,6 +65,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: worker + namespace: default annotations: definition.oam.dev/description: "Long-running scalable backend worker without network endpoint" spec: @@ -89,7 +90,7 @@ spec: }, } - temp, err := LoadTemplate(&tclient, "worker", types.TypeWorkload) + temp, err := LoadTemplate(context.TODO(), &tclient, "worker", types.TypeWorkload) if err != nil { t.Error(err) @@ -172,6 +173,7 @@ metadata: definition.oam.dev/description: "Configures K8s ingress and service to enable web traffic for your service. Please use route trait in cap center for advanced usage." name: ingress + namespace: default spec: status: customStatus: |- @@ -204,7 +206,7 @@ spec: }, } - temp, err := LoadTemplate(&tclient, "ingress", types.TypeTrait) + temp, err := LoadTemplate(context.TODO(), &tclient, "ingress", types.TypeTrait) if err != nil { t.Error(err) diff --git a/pkg/oam/var.go b/pkg/oam/var.go new file mode 100644 index 000000000..c45506e45 --- /dev/null +++ b/pkg/oam/var.go @@ -0,0 +1,6 @@ +package oam + +// SystemDefinitonNamespace golbal value for controller and webhook systemlevel namespace +var ( + SystemDefinitonNamespace string = "vela-system" +) diff --git a/pkg/plugins/suit_test.go b/pkg/plugins/suit_test.go index 1a3588f32..a656e3be2 100644 --- a/pkg/plugins/suit_test.go +++ b/pkg/plugins/suit_test.go @@ -106,7 +106,7 @@ var _ = BeforeSuite(func(done Done) { close(done) }, 60) -var DefinitionNamespace = "testdef" +var DefinitionNamespace = "vela-system" var _ = AfterSuite(func() { By("tearing down the test environment") _ = k8sClient.Delete(context.Background(), &corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: DefinitionNamespace}}) diff --git a/pkg/plugins/testdata/ingressDef.yaml b/pkg/plugins/testdata/ingressDef.yaml index ca6695069..237ecc163 100644 --- a/pkg/plugins/testdata/ingressDef.yaml +++ b/pkg/plugins/testdata/ingressDef.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: TraitDefinition metadata: name: ingress.test + namespace: vela-system spec: appliesToWorkloads: - webservice diff --git a/pkg/plugins/testdata/manualscalars.yaml b/pkg/plugins/testdata/manualscalars.yaml index 6a4283aa5..b00de6b68 100644 --- a/pkg/plugins/testdata/manualscalars.yaml +++ b/pkg/plugins/testdata/manualscalars.yaml @@ -2,7 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: TraitDefinition metadata: name: scaler - namespace: default + namespace: vela-system spec: appliesToWorkloads: - core.oam.dev/v1alpha2.ContainerizedWorkload diff --git a/pkg/plugins/testdata/traitDef.yaml b/pkg/plugins/testdata/traitDef.yaml index d5569fb21..4ad1144b2 100644 --- a/pkg/plugins/testdata/traitDef.yaml +++ b/pkg/plugins/testdata/traitDef.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: TraitDefinition metadata: name: routes.test + namespace: vela-system labels: usecase: forplugintest spec: diff --git a/pkg/plugins/testdata/websvcWorkloadDef.yaml b/pkg/plugins/testdata/websvcWorkloadDef.yaml index 30a0f6925..659889835 100644 --- a/pkg/plugins/testdata/websvcWorkloadDef.yaml +++ b/pkg/plugins/testdata/websvcWorkloadDef.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: webservice.testapps + namespace: vela-system labels: usecase: forplugintest spec: diff --git a/pkg/plugins/testdata/workloadDef.yaml b/pkg/plugins/testdata/workloadDef.yaml index 9f4f7d8e7..642a407fc 100644 --- a/pkg/plugins/testdata/workloadDef.yaml +++ b/pkg/plugins/testdata/workloadDef.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: deployments.testapps + namespace: vela-system labels: usecase: forplugintest spec: diff --git a/pkg/webhook/core.oam.dev/v1alpha2/application/suite_test.go b/pkg/webhook/core.oam.dev/v1alpha2/application/suite_test.go index 142c0d42b..3d18f8910 100644 --- a/pkg/webhook/core.oam.dev/v1alpha2/application/suite_test.go +++ b/pkg/webhook/core.oam.dev/v1alpha2/application/suite_test.go @@ -19,11 +19,14 @@ package application import ( "context" "encoding/json" + "os" "path/filepath" "testing" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" "k8s.io/client-go/kubernetes/scheme" "k8s.io/client-go/rest" @@ -59,10 +62,15 @@ func TestAPIs(t *testing.T) { var _ = BeforeSuite(func(done Done) { logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) - By("bootstrapping test environment") + var yamlPath string + if _, set := os.LookupEnv("COMPATIBILITY_TEST"); set { + yamlPath = "../../../../../test/compatibility-test/testdata" + } else { + yamlPath = filepath.Join("../../../../..", "charts", "vela-core", "crds") + } testEnv = &envtest.Environment{ - CRDDirectoryPaths: []string{filepath.Join("../../../../..", "charts", "vela-core", "crds")}, + CRDDirectoryPaths: []string{yamlPath}, } var err error @@ -86,6 +94,8 @@ var _ = BeforeSuite(func(done Done) { Expect(decoder).ToNot(BeNil()) ctx := context.Background() + ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: "vela-system"}} + Expect(k8sClient.Create(ctx, &ns)).Should(BeNil()) wd := &v1alpha2.WorkloadDefinition{} wDDefJson, _ := yaml.YAMLToJSON([]byte(wDDefYaml)) Expect(json.Unmarshal(wDDefJson, wd)).Should(BeNil()) @@ -111,6 +121,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: worker + namespace: vela-system annotations: definition.oam.dev/description: "Long-running scalable backend worker without network endpoint" spec: @@ -163,6 +174,7 @@ metadata: annotations: definition.oam.dev/description: "Manually scale the app" name: scaler + namespace: vela-system spec: appliesToWorkloads: - webservice diff --git a/pkg/webhook/core.oam.dev/v1alpha2/application/validating_handler.go b/pkg/webhook/core.oam.dev/v1alpha2/application/validating_handler.go index 6475b8b7d..57b880102 100644 --- a/pkg/webhook/core.oam.dev/v1alpha2/application/validating_handler.go +++ b/pkg/webhook/core.oam.dev/v1alpha2/application/validating_handler.go @@ -13,6 +13,7 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" + "github.com/oam-dev/kubevela/pkg/oam/util" ) var _ admission.Handler = &ValidatingHandler{} @@ -53,10 +54,10 @@ func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) a if err := h.Decoder.Decode(req, app); err != nil { return admission.Errored(http.StatusBadRequest, err) } - + ctx = util.SetNnamespaceInCtx(ctx, app.Namespace) switch req.Operation { case admissionv1beta1.Create: - if allErrs := h.ValidateCreate(app); len(allErrs) > 0 { + if allErrs := h.ValidateCreate(ctx, app); len(allErrs) > 0 { return admission.Errored(http.StatusUnprocessableEntity, allErrs.ToAggregate()) } case admissionv1beta1.Update: @@ -65,7 +66,7 @@ func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) a return admission.Errored(http.StatusBadRequest, err) } - if allErrs := h.ValidateUpdate(app, oldApp); len(allErrs) > 0 { + if allErrs := h.ValidateUpdate(ctx, app, oldApp); len(allErrs) > 0 { return admission.Errored(http.StatusUnprocessableEntity, allErrs.ToAggregate()) } default: diff --git a/pkg/webhook/core.oam.dev/v1alpha2/application/validation.go b/pkg/webhook/core.oam.dev/v1alpha2/application/validation.go index 2ad3c267a..47a2196c6 100644 --- a/pkg/webhook/core.oam.dev/v1alpha2/application/validation.go +++ b/pkg/webhook/core.oam.dev/v1alpha2/application/validation.go @@ -1,6 +1,8 @@ package application import ( + "context" + "k8s.io/apimachinery/pkg/util/validation/field" "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" @@ -9,20 +11,20 @@ import ( ) // ValidateCreate validates the Application on creation -func (h *ValidatingHandler) ValidateCreate(app *v1alpha2.Application) field.ErrorList { +func (h *ValidatingHandler) ValidateCreate(ctx context.Context, app *v1alpha2.Application) field.ErrorList { var componentErrs field.ErrorList // try to generate an app file appParser := appfile.NewApplicationParser(h.Client, h.dm) - if _, err := appParser.GenerateAppFile(app.Name, app); err != nil { + if _, err := appParser.GenerateAppFile(ctx, app.Name, app); err != nil { componentErrs = append(componentErrs, field.Invalid(field.NewPath("spec"), app, err.Error())) } return componentErrs } // ValidateUpdate validates the Application on update -func (h *ValidatingHandler) ValidateUpdate(newApp, oldApp *v1alpha2.Application) field.ErrorList { +func (h *ValidatingHandler) ValidateUpdate(ctx context.Context, newApp, oldApp *v1alpha2.Application) field.ErrorList { // check if the newApp is valid - componentErrs := h.ValidateCreate(newApp) + componentErrs := h.ValidateCreate(ctx, newApp) // one can't add a rollout annotation to an existing application if _, exist := oldApp.GetAnnotations()[oam.AnnotationAppRollout]; !exist { if _, exist := newApp.GetAnnotations()[oam.AnnotationAppRollout]; exist { diff --git a/pkg/webhook/core.oam.dev/v1alpha2/applicationconfiguration/validating_handler.go b/pkg/webhook/core.oam.dev/v1alpha2/applicationconfiguration/validating_handler.go index 8e91b3091..187436310 100644 --- a/pkg/webhook/core.oam.dev/v1alpha2/applicationconfiguration/validating_handler.go +++ b/pkg/webhook/core.oam.dev/v1alpha2/applicationconfiguration/validating_handler.go @@ -19,6 +19,7 @@ import ( "github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2" "github.com/oam-dev/kubevela/pkg/oam/discoverymapper" + "github.com/oam-dev/kubevela/pkg/oam/util" ) const ( @@ -94,6 +95,7 @@ func (h *ValidatingHandler) Handle(ctx context.Context, req admission.Request) a return admission.ValidationResponse(true, "") } vAppConfig := &ValidatingAppConfig{} + ctx = util.SetNnamespaceInCtx(ctx, obj.Namespace) if err := vAppConfig.PrepareForValidation(ctx, h.Client, h.Mapper, obj); err != nil { klog.Info("failed preparing information before validation ", " name: ", obj.Name, " errMsg: ", err.Error()) return admission.Denied(err.Error()) diff --git a/test/compatibility-test/convert/main.go b/test/compatibility-test/convert/main.go new file mode 100644 index 000000000..0332a0a8c --- /dev/null +++ b/test/compatibility-test/convert/main.go @@ -0,0 +1,50 @@ +package main // #nosec + +// generate compatibility testdata +import ( + "fmt" + "io/ioutil" + "log" + "os" + "path/filepath" + "strings" +) + +func main() { + var srcdir, dstdir string + if len(os.Args) > 1 { + srcdir = os.Args[1] + dstdir = os.Args[2] + } + err := filepath.Walk(srcdir, func(path string, info os.FileInfo, err error) error { + if err != nil { + fmt.Println(err) + } + if info.IsDir() { + return nil + } + /* #nosec */ + data, err := ioutil.ReadFile(path) + if err != nil { + fmt.Fprintln(os.Stderr, "failed to read file", err) + return err + } + fileName := info.Name() + var newdata string + if fileName == "core.oam.dev_workloaddefinitions.yaml" || fileName == "core.oam.dev_traitdefinitions.yaml" || fileName == "core.oam.dev_scopedefinitions.yaml" { + newdata = strings.ReplaceAll(string(data), "scope: Namespaced", "scope: Cluster") + } else { + newdata = string(data) + } + dstpath := dstdir + "/" + fileName + /* #nosec */ + if err = ioutil.WriteFile(dstpath, []byte(newdata), 0644); err != nil { + fmt.Fprintln(os.Stderr, "failed to write file:", err) + return err + } + return nil + }) + if err != nil { + log.Fatal(err) + } +} diff --git a/test/e2e-test/appconfig_finalizer_test.go b/test/e2e-test/appconfig_finalizer_test.go index 921bb2ffe..47dac6e1a 100644 --- a/test/e2e-test/appconfig_finalizer_test.go +++ b/test/e2e-test/appconfig_finalizer_test.go @@ -150,7 +150,8 @@ var _ = Describe("Finalizer for HealthScope in ApplicationConfiguration", func() // create health scope definition sd := v1alpha2.ScopeDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "healthscopes.core.oam.dev", + Name: "healthscopes.core.oam.dev", + Namespace: "vela-system", }, Spec: v1alpha2.ScopeDefinitionSpec{ AllowComponentOverlap: true, diff --git a/test/e2e-test/component_version_test.go b/test/e2e-test/component_version_test.go index 3b9bc6a44..12d112e21 100644 --- a/test/e2e-test/component_version_test.go +++ b/test/e2e-test/component_version_test.go @@ -533,7 +533,7 @@ var _ = Describe("Component revision", func() { }, ObjectMeta: metav1.ObjectMeta{ Name: "manualscalertraits2.core.oam.dev", - Namespace: namespace, + Namespace: "vela-system", }, Spec: v1alpha2.TraitDefinitionSpec{ RevisionEnabled: true, diff --git a/test/e2e-test/containerized_workload_test.go b/test/e2e-test/containerized_workload_test.go index a6929ce22..6ca6a3ddc 100644 --- a/test/e2e-test/containerized_workload_test.go +++ b/test/e2e-test/containerized_workload_test.go @@ -75,8 +75,9 @@ var _ = Describe("ContainerizedWorkload", func() { label = map[string]string{fakeLabelKey: "containerized-workload"} wd = v1alpha2.WorkloadDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "containerizedworkloads.core.oam.dev", - Labels: label, + Name: "containerizedworkloads.core.oam.dev", + Namespace: "vela-system", + Labels: label, }, Spec: v1alpha2.WorkloadDefinitionSpec{ Reference: v1alpha2.DefinitionReference{ diff --git a/test/e2e-test/health_scope_test.go b/test/e2e-test/health_scope_test.go index bbebebdc7..40840b6cd 100644 --- a/test/e2e-test/health_scope_test.go +++ b/test/e2e-test/health_scope_test.go @@ -70,7 +70,8 @@ var _ = Describe("HealthScope", func() { // create health scope definition sd := v1alpha2.ScopeDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "healthscope.core.oam.dev", + Name: "healthscope.core.oam.dev", + Namespace: "vela-system", }, Spec: v1alpha2.ScopeDefinitionSpec{ AllowComponentOverlap: true, @@ -106,8 +107,9 @@ var _ = Describe("HealthScope", func() { // create a workload definition wd := v1alpha2.WorkloadDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "containerizedworkloads.core.oam.dev", - Labels: label, + Name: "containerizedworkloads.core.oam.dev", + Namespace: "vela-system", + Labels: label, }, Spec: v1alpha2.WorkloadDefinitionSpec{ Reference: v1alpha2.DefinitionReference{ diff --git a/test/e2e-test/kubernetes_workload_test.go b/test/e2e-test/kubernetes_workload_test.go index 4015f3a67..0549ff233 100644 --- a/test/e2e-test/kubernetes_workload_test.go +++ b/test/e2e-test/kubernetes_workload_test.go @@ -63,8 +63,9 @@ var _ = Describe("Test kubernetes native workloads", func() { // create a workload definition for wd := v1alpha2.WorkloadDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "deployments.apps", - Labels: label, + Name: "deployments.apps", + Namespace: "vela-system", + Labels: label, }, Spec: v1alpha2.WorkloadDefinitionSpec{ Reference: v1alpha2.DefinitionReference{ diff --git a/test/e2e-test/suite_test.go b/test/e2e-test/suite_test.go index daff0cefd..e800c3e14 100644 --- a/test/e2e-test/suite_test.go +++ b/test/e2e-test/suite_test.go @@ -106,8 +106,9 @@ var _ = BeforeSuite(func(done Done) { // Create manual scaler trait definition manualscalertrait = v1alpha2.TraitDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "manualscalertraits.core.oam.dev", - Labels: map[string]string{"trait": "manualscalertrait"}, + Name: "manualscalertraits.core.oam.dev", + Namespace: "vela-system", + Labels: map[string]string{"trait": "manualscalertrait"}, }, Spec: v1alpha2.TraitDefinitionSpec{ WorkloadRefPath: "spec.workloadRef", @@ -129,8 +130,9 @@ var _ = BeforeSuite(func(done Done) { extendedmanualscalertrait = v1alpha2.TraitDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "manualscalertraits-extended.core.oam.dev", - Labels: map[string]string{"trait": "manualscalertrait"}, + Name: "manualscalertraits-extended.core.oam.dev", + Namespace: "vela-system", + Labels: map[string]string{"trait": "manualscalertrait"}, }, Spec: v1alpha2.TraitDefinitionSpec{ WorkloadRefPath: "spec.workloadRef", @@ -148,8 +150,9 @@ var _ = BeforeSuite(func(done Done) { // create workload definition for 'containerizedworkload' wd := v1alpha2.WorkloadDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "containerizedworkloads.core.oam.dev", - Labels: label, + Name: "containerizedworkloads.core.oam.dev", + Namespace: "vela-system", + Labels: label, }, Spec: v1alpha2.WorkloadDefinitionSpec{ Reference: v1alpha2.DefinitionReference{ @@ -173,7 +176,8 @@ var _ = BeforeSuite(func(done Done) { // create workload definition for 'deployments' wdDeploy := v1alpha2.WorkloadDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "deployments.apps", + Name: "deployments.apps", + Namespace: "vela-system", }, Spec: v1alpha2.WorkloadDefinitionSpec{ Reference: v1alpha2.DefinitionReference{ diff --git a/test/e2e-test/testdata/revision/trait-def-no-revision.yaml b/test/e2e-test/testdata/revision/trait-def-no-revision.yaml index 3c6538a42..b6f90162f 100644 --- a/test/e2e-test/testdata/revision/trait-def-no-revision.yaml +++ b/test/e2e-test/testdata/revision/trait-def-no-revision.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: TraitDefinition metadata: name: bars.example.com + namespace: vela-system spec: definitionRef: name: bars.example.com \ No newline at end of file diff --git a/test/e2e-test/testdata/revision/trait-def.yaml b/test/e2e-test/testdata/revision/trait-def.yaml index ce7069b85..9e1c35e9c 100644 --- a/test/e2e-test/testdata/revision/trait-def.yaml +++ b/test/e2e-test/testdata/revision/trait-def.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: TraitDefinition metadata: name: bars.example.com + namespace: vela-system spec: revisionEnabled: true definitionRef: diff --git a/test/e2e-test/testdata/revision/workload-def.yaml b/test/e2e-test/testdata/revision/workload-def.yaml index 528a4ec7d..320786fc0 100644 --- a/test/e2e-test/testdata/revision/workload-def.yaml +++ b/test/e2e-test/testdata/revision/workload-def.yaml @@ -2,6 +2,7 @@ apiVersion: core.oam.dev/v1alpha2 kind: WorkloadDefinition metadata: name: bars.example.com + namespace: vela-system spec: definitionRef: name: bars.example.com \ No newline at end of file diff --git a/test/e2e-test/testdata/rollout/clonesetDefinition.yaml b/test/e2e-test/testdata/rollout/clonesetDefinition.yaml new file mode 100644 index 000000000..ccfae7431 --- /dev/null +++ b/test/e2e-test/testdata/rollout/clonesetDefinition.yaml @@ -0,0 +1,106 @@ +# Code generated by KubeVela templates. DO NOT EDIT. +apiVersion: core.oam.dev/v1alpha2 +kind: WorkloadDefinition +metadata: + name: clonesetservice + namespace: vela-system + annotations: + definition.oam.dev/description: "Describes long-running, scalable, containerized services that have a stable network endpoint to receive external network traffic from customers. + If workload type is skipped for any service defined in Appfile, it will be defaulted to `webservice` type." +spec: + definitionRef: + name: clonesets.apps.kruise.io + schematic: + cue: + template: | + output: { + apiVersion: "apps.kruise.io/v1alpha1" + kind: "CloneSet" + metadata: labels: { + "app.oam.dev/component": context.name + } + spec: { + replicas: parameter.replicas + selector: matchLabels: { + "app.oam.dev/component": context.name + } + + template: { + metadata: labels: { + "app.oam.dev/component": context.name + } + + spec: { + containers: [{ + name: context.name + image: parameter.image + + if parameter["cmd"] != _|_ { + command: parameter.cmd + } + + if parameter["env"] != _|_ { + env: parameter.env + } + + if context["config"] != _|_ { + env: context.config + } + + ports: [{ + containerPort: parameter.port + }] + + if parameter["cpu"] != _|_ { + resources: { + limits: + cpu: parameter.cpu + requests: + cpu: parameter.cpu + } + } + }] + } + } + if parameter["updateStrategyType"] != _|_ { + updateStrategy: { + type: parameter.updateStrategyType + } + } + } + } + parameter: { + // +usage=Which image would you like to use for your service + // +short=i + image: string + + // +usage=Commands to run in the container + cmd?: [...string] + + // +usage=Which port do you want customer traffic sent to + // +short=p + port: *80 | int + // +usage=Define arguments by using environment variables + env?: [...{ + // +usage=Environment variable name + name: string + // +usage=The value of the environment variable + value?: string + // +usage=Specifies a source the value of this var should come from + valueFrom?: { + // +usage=Selects a key of a secret in the pod's namespace + secretKeyRef: { + // +usage=The name of the secret in the pod's namespace to select from + name: string + // +usage=The key of the secret to select from. Must be a valid secret key + key: string + } + } + }] + // +usage=Number of CPU units for the service, like `0.5` (0.5 CPU core), `1` (1 CPU core) + cpu?: string + // +usage=Cloneset updateStrategy, candidates are `ReCreate`/`InPlaceIfPossible`/`InPlaceOnly` + updateStrategyType?: string + // +usage=Number of pods in the cloneset + replicas: *5 | int + } \ No newline at end of file diff --git a/test/integration/builder.go b/test/integration/builder.go index af0f6b1d2..3d65cb879 100644 --- a/test/integration/builder.go +++ b/test/integration/builder.go @@ -30,6 +30,7 @@ type wdModifier func(*v1alpha2.WorkloadDefinition) func wdNameAndDef(n string) wdModifier { return func(wd *v1alpha2.WorkloadDefinition) { wd.ObjectMeta.Name = n + wd.ObjectMeta.Namespace = "vela-system" wd.Spec.Reference = v1alpha2.DefinitionReference{ Name: n, }