From 5c33598fe975f01e768733ecca1fdcf49eb2fa03 Mon Sep 17 00:00:00 2001 From: wangyike Date: Fri, 19 Feb 2021 16:53:32 +0800 Subject: [PATCH] modify controller,webhook,api,chart solve failed test add compatibility test for old crd add app ns for cli modify compatibility test solve compatibility problem add testing for GetDefinition func with cluster scope CRD generate code for compatibility-test move testdata generate to makefile optimize ci pipeline for compatibility-test --- .github/workflows/go.yml | 39 ++ Makefile | 12 + apis/core.oam.dev/v1alpha2/core_types.go | 6 +- .../crds/core.oam.dev_scopedefinitions.yaml | 2 +- .../crds/core.oam.dev_traitdefinitions.yaml | 2 +- .../core.oam.dev_workloaddefinitions.yaml | 2 +- .../definitions/containerizedworkloads.yaml | 1 + .../templates/definitions/healthscopes.yaml | 2 +- .../templates/defwithtemplate/ingress.yaml | 1 + .../defwithtemplate/manualscale.yaml | 1 + .../templates/defwithtemplate/task.yaml | 1 + .../templates/defwithtemplate/webservice.yaml | 1 + .../templates/defwithtemplate/worker.yaml | 1 + charts/vela-core/values.yaml | 2 + cmd/core/main.go | 3 + hack/vela-templates/definitions/ingress.yaml | 1 + .../definitions/manualscale.yaml | 1 + hack/vela-templates/definitions/task.yaml | 1 + .../definitions/webservice.yaml | 1 + hack/vela-templates/definitions/worker.yaml | 1 + .../crds/core.oam.dev_scopedefinitions.yaml | 2 +- .../crds/core.oam.dev_traitdefinitions.yaml | 2 +- .../core.oam.dev_workloaddefinitions.yaml | 2 +- pkg/appfile/addon.go | 3 +- pkg/appfile/parser.go | 18 +- pkg/appfile/parser_test.go | 2 +- pkg/commands/dryrun.go | 5 +- .../application/application_controller.go | 5 +- .../application_controller_test.go | 16 +- .../v1alpha2/application/suite_test.go | 15 +- .../applicationconfiguration.go | 1 + .../applicationconfiguration/apply_test.go | 7 +- .../apply_trait_test.go | 3 +- .../applicationconfiguration/render_test.go | 11 +- .../applicationconfiguration/suite_test.go | 22 +- .../application-workload.go | 3 +- .../applicationdeployment_controller.go | 3 + .../applicationdeployment/suite_test.go | 10 +- .../manualscalertrait_controller.go | 3 + .../autoscaler/autoscaler_controller.go | 2 + .../metrics/metricstrait_controller.go | 2 + .../v1alpha1/metrics/suite_test.go | 11 +- .../v1alpha1/routes/route_controller.go | 2 + .../v1alpha1/routes/suite_test.go | 22 +- pkg/oam/util/helper.go | 97 ++-- pkg/oam/util/helper_test.go | 515 +++++++++++++++++- pkg/oam/util/template.go | 16 +- pkg/oam/util/template_test.go | 6 +- pkg/oam/var.go | 6 + pkg/plugins/suit_test.go | 2 +- pkg/plugins/testdata/ingressDef.yaml | 1 + pkg/plugins/testdata/manualscalars.yaml | 2 +- pkg/plugins/testdata/traitDef.yaml | 1 + pkg/plugins/testdata/websvcWorkloadDef.yaml | 1 + pkg/plugins/testdata/workloadDef.yaml | 1 + .../v1alpha2/application/suite_test.go | 16 +- .../application/validating_handler.go | 7 +- .../v1alpha2/application/validation.go | 10 +- .../validating_handler.go | 2 + test/compatibility-test/convert/main.go | 50 ++ test/e2e-test/appconfig_finalizer_test.go | 3 +- test/e2e-test/component_version_test.go | 2 +- test/e2e-test/containerized_workload_test.go | 5 +- test/e2e-test/health_scope_test.go | 8 +- test/e2e-test/kubernetes_workload_test.go | 5 +- test/e2e-test/suite_test.go | 18 +- .../revision/trait-def-no-revision.yaml | 1 + .../e2e-test/testdata/revision/trait-def.yaml | 1 + .../testdata/revision/workload-def.yaml | 1 + .../testdata/rollout/clonesetDefinition.yaml | 106 ++++ test/integration/builder.go | 1 + 71 files changed, 1010 insertions(+), 127 deletions(-) create mode 100644 pkg/oam/var.go create mode 100644 test/compatibility-test/convert/main.go create mode 100644 test/e2e-test/testdata/rollout/clonesetDefinition.yaml 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, }