diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8ae4235e..e6cfceac 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -120,6 +120,9 @@ jobs: with: go-version: ${{ env.GO_VERSION }} + - name: install Kubebuilder + uses: RyanSiu1995/kubebuilder-action@v1 + - name: Cache Go Dependencies uses: actions/cache@v2 with: diff --git a/build b/build index e8fb77d6..3c47eae1 160000 --- a/build +++ b/build @@ -1 +1 @@ -Subproject commit e8fb77d69aefc49dd2e9ead59da21bd719cacb78 +Subproject commit 3c47eae15fc8ae3c3f2f00f11b551cb6c467610a diff --git a/go.mod b/go.mod index 8207bb6d..19624fd9 100644 --- a/go.mod +++ b/go.mod @@ -14,7 +14,7 @@ require ( github.com/pkg/errors v0.9.1 github.com/stretchr/testify v1.4.0 go.uber.org/zap v1.10.0 - golang.org/x/tools v0.0.0-20200630223951-c138986dd9b9 + golang.org/x/tools v0.0.0-20200630223951-c138986dd9b9 // indirect gopkg.in/natefinch/lumberjack.v2 v2.0.0 k8s.io/api v0.18.5 k8s.io/apiextensions-apiserver v0.18.2 diff --git a/pkg/controller/v1alpha2/applicationconfiguration/applicationconfiguration.go b/pkg/controller/v1alpha2/applicationconfiguration/applicationconfiguration.go index a37f88dd..721e789a 100644 --- a/pkg/controller/v1alpha2/applicationconfiguration/applicationconfiguration.go +++ b/pkg/controller/v1alpha2/applicationconfiguration/applicationconfiguration.go @@ -24,12 +24,10 @@ import ( "time" "github.com/pkg/errors" - meta2 "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/client" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" "sigs.k8s.io/controller-runtime/pkg/reconcile" "sigs.k8s.io/controller-runtime/pkg/source" @@ -43,6 +41,7 @@ import ( "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" "github.com/crossplane/oam-kubernetes-runtime/pkg/controller" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/discoverymapper" ) const ( @@ -81,9 +80,9 @@ const ( // Setup adds a controller that reconciles ApplicationConfigurations. func Setup(mgr ctrl.Manager, args controller.Args, l logging.Logger) error { - mapper, err := apiutil.NewDiscoveryRESTMapper(mgr.GetConfig()) + dm, err := discoverymapper.New(mgr.GetConfig()) if err != nil { - return fmt.Errorf("create discovery mapper fail %v", err) + return fmt.Errorf("create discovery dm fail %v", err) } name := "oam/" + strings.ToLower(v1alpha2.ApplicationConfigurationGroupKind) @@ -95,7 +94,7 @@ func Setup(mgr ctrl.Manager, args controller.Args, l logging.Logger) error { Logger: l, RevisionLimit: args.RevisionLimit, }). - Complete(NewReconciler(mgr, mapper, + Complete(NewReconciler(mgr, dm, WithLogger(l.WithValues("controller", name)), WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))))) } @@ -170,13 +169,13 @@ func WithPosthook(name string, hook ControllerHooks) ReconcilerOption { // NewReconciler returns an OAMApplicationReconciler that reconciles ApplicationConfigurations // by rendering and instantiating their Components and Traits. -func NewReconciler(m ctrl.Manager, mapper meta2.RESTMapper, o ...ReconcilerOption) *OAMApplicationReconciler { +func NewReconciler(m ctrl.Manager, dm discoverymapper.DiscoveryMapper, o ...ReconcilerOption) *OAMApplicationReconciler { r := &OAMApplicationReconciler{ client: m.GetClient(), scheme: m.GetScheme(), components: &components{ client: m.GetClient(), - mapper: mapper, + dm: dm, params: ParameterResolveFn(resolve), workload: ResourceRenderFn(renderWorkload), trait: ResourceRenderFn(renderTrait), @@ -184,7 +183,7 @@ func NewReconciler(m ctrl.Manager, mapper meta2.RESTMapper, o ...ReconcilerOptio workloads: &workloads{ client: resource.NewAPIPatchingApplicator(m.GetClient()), rawClient: m.GetClient(), - mapper: mapper, + dm: dm, }, gc: GarbageCollectorFn(eligible), log: logging.NewNopLogger(), @@ -269,7 +268,7 @@ func (r *OAMApplicationReconciler) Reconcile(req reconcile.Request) (result reco workloads, depStatus, err := r.components.Render(ctx, ac) if err != nil { - log.Debug("Cannot render components", "error", err, "requeue-after", time.Now().Add(shortWait)) + log.Info("Cannot render components", "error", err, "requeue-after", time.Now().Add(shortWait)) r.record.Event(ac, event.Warning(reasonCannotRenderComponents, err)) ac.SetConditions(v1alpha1.ReconcileError(errors.Wrap(err, errRenderComponents))) return reconcile.Result{RequeueAfter: shortWait}, errors.Wrap(r.client.Status().Update(ctx, ac), errUpdateAppConfigStatus) diff --git a/pkg/controller/v1alpha2/applicationconfiguration/applicationconfiguration_test.go b/pkg/controller/v1alpha2/applicationconfiguration/applicationconfiguration_test.go index e2505658..721ee254 100644 --- a/pkg/controller/v1alpha2/applicationconfiguration/applicationconfiguration_test.go +++ b/pkg/controller/v1alpha2/applicationconfiguration/applicationconfiguration_test.go @@ -887,7 +887,7 @@ func TestDependency(t *testing.T) { t.Fatal(err) } - mapper := mock.NewMockMapper() + mapper := mock.NewMockDiscoveryMapper() type args struct { components []v1alpha2.ApplicationConfigurationComponent @@ -1299,7 +1299,7 @@ func TestDependency(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { c := components{ - mapper: mapper, + dm: mapper, client: &test.MockClient{ MockGet: test.MockGetFn(func(ctx context.Context, key client.ObjectKey, obj runtime.Object) error { if obj.GetObjectKind().GroupVersionKind().Kind == "Workload" { diff --git a/pkg/controller/v1alpha2/applicationconfiguration/apply.go b/pkg/controller/v1alpha2/applicationconfiguration/apply.go index c0e17773..d119487f 100644 --- a/pkg/controller/v1alpha2/applicationconfiguration/apply.go +++ b/pkg/controller/v1alpha2/applicationconfiguration/apply.go @@ -19,8 +19,6 @@ package applicationconfiguration import ( "context" - meta2 "k8s.io/apimachinery/pkg/api/meta" - runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" "github.com/crossplane/crossplane-runtime/pkg/fieldpath" "github.com/crossplane/crossplane-runtime/pkg/meta" @@ -32,6 +30,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/discoverymapper" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util" ) @@ -78,7 +77,7 @@ func (fn WorkloadApplyFns) Finalize(ctx context.Context, ac *v1alpha2.Applicatio type workloads struct { client resource.Applicator rawClient client.Client - mapper meta2.RESTMapper + dm discoverymapper.DiscoveryMapper } func (a *workloads) Apply(ctx context.Context, status []v1alpha2.WorkloadStatus, w []Workload, ao ...resource.ApplyOption) error { @@ -186,7 +185,7 @@ func findDereferencedScopes(statusScopes []v1alpha2.WorkloadScope, scopes []unst func (a *workloads) applyScope(ctx context.Context, wl Workload, s unstructured.Unstructured, workloadRef runtimev1alpha1.TypedReference) error { // get ScopeDefinition - scopeDefinition, err := util.FetchScopeDefinition(ctx, a.rawClient, a.mapper, &s) + scopeDefinition, err := util.FetchScopeDefinition(ctx, a.rawClient, a.dm, &s) if err != nil { return errors.Wrapf(err, errFmtGetScopeDefinition, s.GetAPIVersion(), s.GetKind(), s.GetName()) } @@ -240,7 +239,7 @@ func (a *workloads) applyScopeRemoval(ctx context.Context, namespace string, wr return errors.Wrapf(err, errFmtApplyScope, s.Reference.APIVersion, s.Reference.Kind, s.Reference.Name) } - scopeDefinition, err := util.FetchScopeDefinition(ctx, a.rawClient, a.mapper, &scopeObject) + scopeDefinition, err := util.FetchScopeDefinition(ctx, a.rawClient, a.dm, &scopeObject) if err != nil { return errors.Wrapf(err, errFmtGetScopeDefinition, scopeObject.GetAPIVersion(), scopeObject.GetKind(), scopeObject.GetName()) } diff --git a/pkg/controller/v1alpha2/applicationconfiguration/apply_test.go b/pkg/controller/v1alpha2/applicationconfiguration/apply_test.go index 129bf9c5..90ac3a55 100644 --- a/pkg/controller/v1alpha2/applicationconfiguration/apply_test.go +++ b/pkg/controller/v1alpha2/applicationconfiguration/apply_test.go @@ -21,8 +21,6 @@ import ( "fmt" "testing" - "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/mock" - "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" "github.com/crossplane/crossplane-runtime/pkg/fieldpath" "github.com/crossplane/crossplane-runtime/pkg/resource" @@ -36,6 +34,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/client" "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/mock" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util" ) @@ -320,9 +319,9 @@ func TestApplyWorkloads(t *testing.T) { for name, tc := range cases { t.Run(name, func(t *testing.T) { - mapper := mock.NewMockMapper() + mapper := mock.NewMockDiscoveryMapper() - w := workloads{client: tc.client, rawClient: tc.rawClient, mapper: mapper} + w := workloads{client: tc.client, rawClient: tc.rawClient, dm: mapper} err := w.Apply(tc.args.ctx, tc.args.ws, tc.args.w) if diff := cmp.Diff(tc.want, err, test.EquateErrors()); diff != "" { @@ -467,8 +466,8 @@ func TestFinalizeWorkloadScopes(t *testing.T) { for _, tc := range cases { t.Run(tc.caseName, func(t *testing.T) { acTest := ac - mapper := mock.NewMockMapper() - w := workloads{client: tc.client, rawClient: tc.rawClient, mapper: mapper} + mapper := mock.NewMockDiscoveryMapper() + w := workloads{client: tc.client, rawClient: tc.rawClient, dm: mapper} err := w.Finalize(ctx, &acTest) if diff := cmp.Diff(tc.wantErr, err, test.EquateErrors()); diff != "" { diff --git a/pkg/controller/v1alpha2/applicationconfiguration/dependency_test.go b/pkg/controller/v1alpha2/applicationconfiguration/dependency_test.go new file mode 100644 index 00000000..ec509327 --- /dev/null +++ b/pkg/controller/v1alpha2/applicationconfiguration/dependency_test.go @@ -0,0 +1,501 @@ +package applicationconfiguration + +import ( + "context" + "fmt" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" + corev1 "k8s.io/api/core/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/reconcile" + + "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util" +) + +var _ = Describe("Resource Dependency in an ApplicationConfiguration", func() { + ctx := context.Background() + namespace := "appconfig-dependency-test" + var ns corev1.Namespace + tempFoo := &unstructured.Unstructured{} + tempFoo.SetAPIVersion("example.com/v1") + tempFoo.SetKind("Foo") + tempFoo.SetNamespace(namespace) + outName := "data-output" + out := tempFoo.DeepCopy() + out.SetName(outName) + inName := "data-input" + in := tempFoo.DeepCopy() + in.SetName(inName) + componentOutName := "component-out" + componentInName := "component-in" + + BeforeEach(func() { + ns = corev1.Namespace{ + ObjectMeta: metav1.ObjectMeta{ + Name: namespace, + }, + } + Eventually( + func() error { + return k8sClient.Create(ctx, &ns) + }, + time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + + By(" Create two components, one for data output and one for data input") + compOut := v1alpha2.Component{ + ObjectMeta: metav1.ObjectMeta{ + Name: componentOutName, + Namespace: namespace, + }, + Spec: v1alpha2.ComponentSpec{ + Workload: runtime.RawExtension{ + Object: out, + }, + }, + } + Expect(k8sClient.Create(ctx, &compOut)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + compIn := v1alpha2.Component{ + ObjectMeta: metav1.ObjectMeta{ + Name: componentInName, + Namespace: namespace, + }, + Spec: v1alpha2.ComponentSpec{ + Workload: runtime.RawExtension{ + Object: in, + }, + }, + } + Expect(k8sClient.Create(ctx, &compIn)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + + }) + AfterEach(func() { + logf.Log.Info("Clean up resources") + // delete the namespace with all its resources + Expect(k8sClient.Delete(ctx, in)).Should(BeNil()) + Expect(k8sClient.Delete(ctx, out)).Should(BeNil()) + }) + + // common function for verification + verify := func(appConfigName, reason string) { + + appconfigKey := client.ObjectKey{ + Name: appConfigName, + Namespace: namespace, + } + + // Verification before satisfying dependency + By("Checking that resource which accepts data isn't created yet") + inFooKey := client.ObjectKey{ + Name: inName, + Namespace: namespace, + } + inFoo := tempFoo.DeepCopy() + By(fmt.Sprintf("Checking on resource that inputs data Key: %s", inFooKey)) + Expect(k8sClient.Get(ctx, inFooKey, inFoo)).Should(&util.NotFoundMatcher{}) + + By("Reconcile") + req := reconcile.Request{NamespacedName: appconfigKey} + Expect(func() error { _, err := reconciler.Reconcile(req); return err }()).Should(BeNil()) + + outFooKey := client.ObjectKey{ + Name: outName, + Namespace: namespace, + } + outFoo := tempFoo.DeepCopy() + By(fmt.Sprintf("Checking that resource which provides(output) data is created, Key %s", outFoo)) + Eventually(func() error { + err := k8sClient.Get(ctx, outFooKey, outFoo) + if err != nil { + // Try 3 (= 1s/300ms) times + reconciler.Reconcile(req) + } + return err + }, time.Second, 300*time.Millisecond).Should(BeNil()) + + By("Reconcile") + Expect(func() error { _, err := reconciler.Reconcile(req); return err }()).Should(BeNil()) + + By("Verify the appconfig's dependency is unsatisfied, waiting for the outside controller to satisfy the requirement") + appconfig := &v1alpha2.ApplicationConfiguration{} + depStatus := v1alpha2.DependencyStatus{ + Unsatisfied: []v1alpha2.UnstaifiedDependency{{ + Reason: reason, + From: v1alpha2.DependencyFromObject{ + TypedReference: v1alpha1.TypedReference{ + APIVersion: tempFoo.GetAPIVersion(), + Name: outName, + Kind: tempFoo.GetKind(), + }, + FieldPath: "status.key", + }, + To: v1alpha2.DependencyToObject{ + TypedReference: v1alpha1.TypedReference{ + APIVersion: tempFoo.GetAPIVersion(), + Name: inName, + Kind: tempFoo.GetKind(), + }, + FieldPaths: []string{ + "spec.key", + }}}}} + logf.Log.Info("Checking on appconfig", "Key", appconfigKey) + Expect(func() v1alpha2.DependencyStatus { + k8sClient.Get(ctx, appconfigKey, appconfig) + return appconfig.Status.Dependency + }()).Should(Equal(depStatus)) + + // fill value to fieldPath + Expect(unstructured.SetNestedField(outFoo.Object, "test", "status", "key")).Should(BeNil()) + Expect(k8sClient.Update(ctx, outFoo)).Should(Succeed()) + + By("Reconcile") + Expect(func() error { _, err := reconciler.Reconcile(req); return err }()).Should(BeNil()) + + // Verification after satisfying dependency + By("Checking that resource which accepts data is created now") + logf.Log.Info("Checking on resource that inputs data", "Key", inFooKey) + + Eventually(func() error { + err := k8sClient.Get(ctx, inFooKey, inFoo) + if err != nil { + // Try 3 (= 1s/300ms) times + reconciler.Reconcile(req) + } + return err + }, time.Second, 300*time.Millisecond).Should(BeNil()) + + By("Verify the appconfig's dependency is satisfied") + appconfig = &v1alpha2.ApplicationConfiguration{} + Eventually(func() []v1alpha2.UnstaifiedDependency { + k8sClient.Get(ctx, appconfigKey, appconfig) + if appconfig.Status.Dependency.Unsatisfied != nil { + // Try 3 (= 1s/300ms) times + reconciler.Reconcile(req) + } + return appconfig.Status.Dependency.Unsatisfied + }, time.Second, 300*time.Millisecond).Should(BeNil()) + } + + It("trait depends on another trait", func() { + label := map[string]string{"trait": "trait"} + // Define a workload + wl := tempFoo.DeepCopy() + wl.SetName("workload") + // Create a component + componentName := "component" + comp := v1alpha2.Component{ + ObjectMeta: metav1.ObjectMeta{ + Name: componentName, + Namespace: namespace, + Labels: label, + }, + Spec: v1alpha2.ComponentSpec{ + Workload: runtime.RawExtension{ + Object: wl, + }, + }, + } + Expect(k8sClient.Create(ctx, &comp)).Should(BeNil()) + logf.Log.Info("Creating component", "Name", comp.Name, "Namespace", comp.Namespace) + // Create application configuration + appConfigName := "appconfig-trait-trait" + appConfig := v1alpha2.ApplicationConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: appConfigName, + Namespace: namespace, + Labels: label, + }, + Spec: v1alpha2.ApplicationConfigurationSpec{ + Components: []v1alpha2.ApplicationConfigurationComponent{{ + ComponentName: componentName, + Traits: []v1alpha2.ComponentTrait{{ + Trait: runtime.RawExtension{ + Object: out, + }, + DataOutputs: []v1alpha2.DataOutput{{ + Name: "trait-trait", + FieldPath: "status.key", + }}}, { + Trait: runtime.RawExtension{ + Object: in, + }, + DataInputs: []v1alpha2.DataInput{{ + ValueFrom: v1alpha2.DataInputValueFrom{ + DataOutputName: "trait-trait", + }, + ToFieldPaths: []string{"spec.key"}, + }}, + }}, + }}}, + } + logf.Log.Info("Creating application config", "Name", appConfig.Name, "Namespace", appConfig.Namespace) + Expect(k8sClient.Create(ctx, &appConfig)).Should(BeNil()) + verify(appConfigName, "status.key not found in object") + }) + + It("component depends on another component", func() { + label := map[string]string{"component": "component"} + // Create application configuration + appConfigName := "appconfig-comp-comp" + appConfig := v1alpha2.ApplicationConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: appConfigName, + Namespace: namespace, + Labels: label, + }, + Spec: v1alpha2.ApplicationConfigurationSpec{ + Components: []v1alpha2.ApplicationConfigurationComponent{{ + ComponentName: componentOutName, + DataOutputs: []v1alpha2.DataOutput{{ + Name: "comp-comp", + FieldPath: "status.key", + }}}, { + ComponentName: componentInName, + DataInputs: []v1alpha2.DataInput{{ + ValueFrom: v1alpha2.DataInputValueFrom{ + DataOutputName: "comp-comp", + }, + ToFieldPaths: []string{"spec.key"}, + }}}}}, + } + logf.Log.Info("Creating application config", "Name", appConfig.Name, "Namespace", appConfig.Namespace) + Expect(k8sClient.Create(ctx, &appConfig)).Should(BeNil()) + verify(appConfigName, "status.key not found in object") + }) + + It("component depends on trait", func() { + label := map[string]string{"trait": "component"} + // Create application configuration + appConfigName := "appconfig-trait-comp" + appConfig := v1alpha2.ApplicationConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: appConfigName, + Namespace: namespace, + Labels: label, + }, + Spec: v1alpha2.ApplicationConfigurationSpec{ + Components: []v1alpha2.ApplicationConfigurationComponent{{ + ComponentName: componentInName, + DataInputs: []v1alpha2.DataInput{{ + ValueFrom: v1alpha2.DataInputValueFrom{ + DataOutputName: "trait-comp", + }, + ToFieldPaths: []string{"spec.key"}, + }}, + Traits: []v1alpha2.ComponentTrait{{ + Trait: runtime.RawExtension{ + Object: out, + }, + DataOutputs: []v1alpha2.DataOutput{{ + Name: "trait-comp", + FieldPath: "status.key", + }}}}}}}, + } + logf.Log.Info("Creating application config", "Name", appConfig.Name, "Namespace", appConfig.Namespace) + Expect(k8sClient.Create(ctx, &appConfig)).Should(BeNil()) + verify(appConfigName, "status.key not found in object") + }) + + It("trait depends on component", func() { + label := map[string]string{"component": "trait"} + // Create application configuration + appConfigName := "appconfig-comp-trait" + appConfig := v1alpha2.ApplicationConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: appConfigName, + Namespace: namespace, + Labels: label, + }, + Spec: v1alpha2.ApplicationConfigurationSpec{ + Components: []v1alpha2.ApplicationConfigurationComponent{{ + ComponentName: componentOutName, + DataOutputs: []v1alpha2.DataOutput{{ + Name: "comp-trait", + FieldPath: "status.key", + }}, + Traits: []v1alpha2.ComponentTrait{{ + Trait: runtime.RawExtension{ + Object: in, + }, + DataInputs: []v1alpha2.DataInput{{ + ValueFrom: v1alpha2.DataInputValueFrom{ + DataOutputName: "comp-trait", + }, + ToFieldPaths: []string{"spec.key"}, + }}}}}}}, + } + logf.Log.Info("Creating application config", "Name", appConfig.Name, "Namespace", appConfig.Namespace) + Expect(k8sClient.Create(ctx, &appConfig)).Should(BeNil()) + verify(appConfigName, "status.key not found in object") + }) + + It("component depends on trait with updated condition", func() { + label := map[string]string{"trait": "component", "app-hash": "hash-v1"} + // Create application configuration + appConfigName := "appconfig-trait-comp-update" + appConfig := v1alpha2.ApplicationConfiguration{ + ObjectMeta: metav1.ObjectMeta{ + Name: appConfigName, + Namespace: namespace, + Labels: label, + }, + Spec: v1alpha2.ApplicationConfigurationSpec{ + Components: []v1alpha2.ApplicationConfigurationComponent{{ + ComponentName: componentInName, + DataInputs: []v1alpha2.DataInput{{ + ValueFrom: v1alpha2.DataInputValueFrom{ + DataOutputName: "trait-comp", + }, + ToFieldPaths: []string{"spec.key"}}}, + Traits: []v1alpha2.ComponentTrait{{ + Trait: runtime.RawExtension{ + Object: out, + }, + DataOutputs: []v1alpha2.DataOutput{{ + Name: "trait-comp", + FieldPath: "status.key", + Conditions: []v1alpha2.ConditionRequirement{{ + Operator: v1alpha2.ConditionEqual, + ValueFrom: v1alpha2.ValueFrom{FieldPath: "metadata.labels.app-hash"}, + FieldPath: "status.app-hash", + }}}}}}}}}, + } + logf.Log.Info("Creating application config", "Name", appConfig.Name, "Namespace", appConfig.Namespace) + Expect(k8sClient.Create(ctx, &appConfig)).Should(BeNil()) + + By("Reconcile") + appconfigKey := client.ObjectKey{ + Name: appConfigName, + Namespace: namespace, + } + req := reconcile.Request{NamespacedName: appconfigKey} + Expect(func() error { _, err := reconciler.Reconcile(req); return err }()).Should(BeNil()) + + By("Checking that resource which accepts data isn't created yet") + inFooKey := client.ObjectKey{ + Name: inName, + Namespace: namespace, + } + inFoo := tempFoo.DeepCopy() + logf.Log.Info("Checking on resource that inputs data", "Key", inFooKey) + Expect(k8sClient.Get(ctx, inFooKey, inFoo)).Should(&util.NotFoundMatcher{}) + + By("Reconcile") + Expect(func() error { _, err := reconciler.Reconcile(req); return err }()).Should(BeNil()) + + By("Checking that resource which provides data is created") + // Originally the trait has value in `status.key`, but the hash label is old + outFooKey := client.ObjectKey{ + Name: outName, + Namespace: namespace, + } + outFoo := tempFoo.DeepCopy() + Eventually(func() error { + err := k8sClient.Get(ctx, outFooKey, outFoo) + if err != nil { + // Try 3 (= 1s/300ms) times + reconciler.Reconcile(req) + } + return err + }, time.Second, 300*time.Millisecond).Should(BeNil()) + + err := unstructured.SetNestedField(outFoo.Object, "test", "status", "key") + Expect(err).Should(BeNil()) + err = unstructured.SetNestedField(outFoo.Object, "hash-v1", "status", "app-hash") + Expect(err).Should(BeNil()) + Expect(k8sClient.Update(ctx, outFoo)).Should(Succeed()) + + By("Reconcile") + Expect(func() error { _, err := reconciler.Reconcile(req); return err }()).Should(BeNil()) + + // Verification after satisfying dependency + By("Verify the appconfig's dependency is satisfied") + newAppConfig := &v1alpha2.ApplicationConfiguration{} + + Eventually(func() []v1alpha2.UnstaifiedDependency { + var tempApp = &v1alpha2.ApplicationConfiguration{} + err = k8sClient.Get(ctx, appconfigKey, tempApp) + tempApp.DeepCopyInto(newAppConfig) + if err != nil || tempApp.Status.Dependency.Unsatisfied != nil { + // Try 3 (= 1s/300ms) times + reconciler.Reconcile(req) + } + return tempApp.Status.Dependency.Unsatisfied + }(), time.Second, 300*time.Millisecond).Should(BeNil()) + + By("Checking that resource which accepts data is created now") + logf.Log.Info("Checking on resource that inputs data", "Key", inFooKey) + Expect(k8sClient.Get(ctx, inFooKey, inFoo)).Should(BeNil()) + + By("Update AppConfig with new version") + newAppConfig.Labels["app-hash"] = "hash-v2" + Expect(k8sClient.Update(ctx, newAppConfig)).Should(BeNil()) + time.Sleep(time.Second) + By("Reconcile") + Expect(func() error { _, err := reconciler.Reconcile(req); return err }()).Should(BeNil()) + + By("Verify the appconfig's dependency should be unsatisfied, because requirementCondition valueFrom not match") + depStatus := v1alpha2.DependencyStatus{ + Unsatisfied: []v1alpha2.UnstaifiedDependency{{ + Reason: "got(hash-v1) expected to be hash-v2", + From: v1alpha2.DependencyFromObject{ + TypedReference: v1alpha1.TypedReference{ + APIVersion: tempFoo.GetAPIVersion(), + Name: outName, + Kind: tempFoo.GetKind(), + }, + FieldPath: "status.key", + }, + To: v1alpha2.DependencyToObject{ + TypedReference: v1alpha1.TypedReference{ + APIVersion: tempFoo.GetAPIVersion(), + Name: inName, + Kind: tempFoo.GetKind(), + }, + FieldPaths: []string{ + "spec.key", + }}}}, + } + Expect(func() v1alpha2.DependencyStatus { + k8sClient.Get(ctx, appconfigKey, newAppConfig) + return newAppConfig.Status.Dependency + }()).Should(Equal(depStatus)) + + By("Update trait resource to meet the requirement") + Expect(k8sClient.Get(ctx, outFooKey, outFoo)).Should(BeNil()) // Get the latest before update + Expect(unstructured.SetNestedField(outFoo.Object, "test-new", "status", "key")).Should(BeNil()) + Expect(unstructured.SetNestedField(outFoo.Object, "hash-v2", "status", "app-hash")).Should(BeNil()) + Expect(k8sClient.Update(ctx, outFoo)).Should(Succeed()) + + By("Reconcile") + Expect(func() error { _, err := reconciler.Reconcile(req); return err }()).Should(BeNil()) + + By("Verify the appconfig's dependency is satisfied") + Eventually( + func() []v1alpha2.UnstaifiedDependency { + tempAppConfig := &v1alpha2.ApplicationConfiguration{} + err := k8sClient.Get(ctx, appconfigKey, tempAppConfig) + if err != nil || tempAppConfig.Status.Dependency.Unsatisfied != nil { + // Try 3 (= 1s/300ms) times + reconciler.Reconcile(req) + } + return tempAppConfig.Status.Dependency.Unsatisfied + }(), time.Second, 300*time.Millisecond).Should(BeNil()) + + By("Checking that resource which accepts data is updated") + Expect(func() string { + k8sClient.Get(ctx, inFooKey, inFoo) + outdata, _, _ := unstructured.NestedString(inFoo.Object, "spec", "key") + return outdata + }()).Should(Equal("test-new")) + + }) +}) diff --git a/pkg/controller/v1alpha2/applicationconfiguration/render.go b/pkg/controller/v1alpha2/applicationconfiguration/render.go index 7b1c3122..b9b2f01c 100644 --- a/pkg/controller/v1alpha2/applicationconfiguration/render.go +++ b/pkg/controller/v1alpha2/applicationconfiguration/render.go @@ -27,7 +27,6 @@ import ( "github.com/crossplane/crossplane-runtime/pkg/resource" "github.com/pkg/errors" corev1 "k8s.io/api/core/v1" - "k8s.io/apimachinery/pkg/api/meta" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/types" @@ -36,6 +35,7 @@ import ( "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/discoverymapper" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util" ) @@ -84,7 +84,7 @@ var _ ComponentRenderer = &components{} type components struct { client client.Reader - mapper meta.RESTMapper + dm discoverymapper.DiscoveryMapper params ParameterResolver workload ResourceRenderer trait ResourceRenderer @@ -213,7 +213,7 @@ func (r *components) renderTrait(ctx context.Context, ct v1alpha2.ComponentTrait setTraitProperties(t, traitName, ac.GetNamespace(), ref) - traitDef, err := util.FetchTraitDefinition(ctx, r.client, r.mapper, t) + traitDef, err := util.FetchTraitDefinition(ctx, r.client, r.dm, t) if err != nil { return nil, nil, errors.Wrapf(err, errFmtGetTraitDefinition, t.GetAPIVersion(), t.GetKind(), t.GetName()) } diff --git a/pkg/controller/v1alpha2/applicationconfiguration/render_test.go b/pkg/controller/v1alpha2/applicationconfiguration/render_test.go index e2212e4d..b3a739cd 100644 --- a/pkg/controller/v1alpha2/applicationconfiguration/render_test.go +++ b/pkg/controller/v1alpha2/applicationconfiguration/render_test.go @@ -21,9 +21,6 @@ import ( "encoding/json" "testing" - "k8s.io/apimachinery/pkg/api/meta" - "k8s.io/apimachinery/pkg/runtime/schema" - "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/mock" "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" @@ -503,7 +500,7 @@ func TestRenderComponents(t *testing.T) { } for name, tc := range cases { t.Run(name, func(t *testing.T) { - r := &components{tc.fields.client, mock.NewMockMapper(), tc.fields.params, tc.fields.workload, tc.fields.trait} + 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) 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) @@ -849,7 +846,7 @@ func TestRenderTraitWithoutMetadataName(t *testing.T) { } for name, tc := range cases { t.Run(name, func(t *testing.T) { - r := &components{tc.fields.client, mock.NewMockMapper(), tc.fields.params, tc.fields.workload, tc.fields.trait} + 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) 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"+ @@ -888,14 +885,9 @@ func TestGetDefinitionName(t *testing.T) { } for name, ti := range tests { t.Run(name, func(t *testing.T) { - mapper := func(resource string) *mock.Mapper { - m := mock.NewMockMapper() - m.MockRESTMapping = func(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { - return &meta.RESTMapping{Resource: schema.GroupVersionResource{Resource: resource}}, nil - } - return m - }(ti.resource) - got, err := util.GetDefinitionName(mapper, ti.u, "") + m := mock.NewMockDiscoveryMapper() + m.MockRESTMapping = mock.NewMockRESTMapping(ti.resource) + got, err := util.GetDefinitionName(m, ti.u, "") assert.NoError(t, err) if got != ti.exp { t.Errorf("%s getCRDName want %s got %s ", ti.reason, ti.exp, got) @@ -1008,10 +1000,8 @@ func TestSetTraitProperties(t *testing.T) { expU.SetOwnerReferences([]metav1.OwnerReference{{Name: "comp1"}}) } -var scheme = runtime.NewScheme() - func TestRenderTraitName(t *testing.T) { - + var scheme = runtime.NewScheme() assert.NoError(t, clientgoscheme.AddToScheme(scheme)) assert.NoError(t, core.AddToScheme(scheme)) namespace := "ns" diff --git a/pkg/controller/v1alpha2/applicationconfiguration/suite_test.go b/pkg/controller/v1alpha2/applicationconfiguration/suite_test.go new file mode 100644 index 00000000..d30a5f4c --- /dev/null +++ b/pkg/controller/v1alpha2/applicationconfiguration/suite_test.go @@ -0,0 +1,192 @@ +package applicationconfiguration + +import ( + "context" + "path/filepath" + "testing" + "time" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + + "github.com/crossplane/crossplane-runtime/pkg/logging" + crdv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1" + "k8s.io/apimachinery/pkg/api/meta" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + clientgoscheme "k8s.io/client-go/kubernetes/scheme" + "k8s.io/client-go/rest" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/client" + "sigs.k8s.io/controller-runtime/pkg/envtest" + "sigs.k8s.io/controller-runtime/pkg/envtest/printer" + logf "sigs.k8s.io/controller-runtime/pkg/log" + "sigs.k8s.io/controller-runtime/pkg/log/zap" + controllerscheme "sigs.k8s.io/controller-runtime/pkg/scheme" + + "github.com/crossplane/oam-kubernetes-runtime/apis/core" + "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/discoverymapper" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util" + // +kubebuilder:scaffold:imports +) + +var reconciler *OAMApplicationReconciler +var mgrclose chan struct{} +var testEnv *envtest.Environment +var cfg *rest.Config +var k8sClient client.Client +var scheme = runtime.NewScheme() +var crd crdv1.CustomResourceDefinition + +func TestReconcilder(t *testing.T) { + RegisterFailHandler(Fail) + + RunSpecsWithDefaultAndCustomReporters(t, + "OAM Core Resource Controller Unit test Suite", + []Reporter{printer.NewlineReporter{}}) +} + +var _ = BeforeSuite(func(done Done) { + ctx := context.Background() + By("Bootstrapping test environment") + testEnv = &envtest.Environment{ + CRDDirectoryPaths: []string{ + filepath.Join("../../../..", "charts/oam-kubernetes-runtime/crds"), // this has all the required CRDs, + }, + } + var err error + cfg, err = testEnv.Start() + Expect(err).ToNot(HaveOccurred()) + Expect(cfg).ToNot(BeNil()) + + logf.SetLogger(zap.New(zap.UseDevMode(true), zap.WriteTo(GinkgoWriter))) + Expect(clientgoscheme.AddToScheme(scheme)).Should(BeNil()) + Expect(core.AddToScheme(scheme)).Should(BeNil()) + Expect(crdv1.AddToScheme(scheme)).Should(BeNil()) + depExample := &unstructured.Unstructured{} + depExample.SetGroupVersionKind(schema.GroupVersionKind{ + Group: "example.com", + Version: "v1", + Kind: "Foo", + }) + depSchemeBuilder := &controllerscheme.Builder{GroupVersion: schema.GroupVersion{Group: "example.com", Version: "v1"}} + depSchemeBuilder.Register(depExample.DeepCopyObject()) + Expect(depSchemeBuilder.AddToScheme(scheme)).Should(BeNil()) + + By("Setting up kubernetes client") + k8sClient, err = client.New(cfg, client.Options{Scheme: scheme}) + if err != nil { + logf.Log.Error(err, "failed to create k8sClient") + Fail("setup failed") + } + By("Finished setting up test environment") + + By("Creating Reconciler for appconfig") + mgr, err := ctrl.NewManager(cfg, ctrl.Options{Scheme: scheme, MetricsBindAddress: "0"}) + Expect(err).Should(BeNil()) + mgrclose = make(chan struct{}) + go mgr.Start(mgrclose) + + // Create a crd for appconfig dependency test + crd = crdv1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo.example.com", + Labels: map[string]string{"crd": "dependency"}, + }, + Spec: crdv1.CustomResourceDefinitionSpec{ + Group: "example.com", + Names: crdv1.CustomResourceDefinitionNames{ + Kind: "Foo", + ListKind: "FooList", + Plural: "foo", + Singular: "foo", + }, + Versions: []crdv1.CustomResourceDefinitionVersion{{ + Name: "v1", + Served: true, + Storage: true, + Schema: &crdv1.CustomResourceValidation{ + OpenAPIV3Schema: &crdv1.JSONSchemaProps{ + Type: "object", + Properties: map[string]crdv1.JSONSchemaProps{ + "spec": { + Type: "object", + Properties: map[string]crdv1.JSONSchemaProps{ + "key": {Type: "string"}, + }}, + "status": { + Type: "object", + Properties: map[string]crdv1.JSONSchemaProps{ + "key": {Type: "string"}, + "app-hash": {Type: "string"}, + }}}}}}, + }, + Scope: crdv1.NamespaceScoped, + }, + } + Expect(k8sClient.Create(context.Background(), &crd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + By("Created a crd for appconfig dependency test") + + dm, err := discoverymapper.New(cfg) + Expect(err).Should(BeNil()) + + var mapping *meta.RESTMapping + Eventually(func() error { + mapping, err = dm.RESTMapping(schema.GroupKind{ + Group: "example.com", + Kind: "Foo", + }, "v1") + return err + }, time.Second*30, time.Millisecond*500).Should(BeNil()) + Expect(mapping.Resource.Resource).Should(Equal("foo")) + + reconciler = NewReconciler(mgr, dm, WithLogger(logging.NewLogrLogger(ctrl.Log.WithName("suit-test-appconfig")))) + + By("Creating workload definition and trait definition") + wd := v1alpha2.WorkloadDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo.example.com", + }, + Spec: v1alpha2.WorkloadDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: "foo.example.com", + }, + }, + } + td := v1alpha2.TraitDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo.example.com", + }, + Spec: v1alpha2.TraitDefinitionSpec{ + Reference: v1alpha2.DefinitionReference{ + Name: "foo.example.com", + }, + }, + } + // For some reason, WorkloadDefinition is created as a Cluster scope object + Expect(k8sClient.Create(ctx, &wd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + // For some reason, TraitDefinition is created as a Cluster scope object + Expect(k8sClient.Create(ctx, &td)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) + + close(done) +}, 300) + +var _ = AfterSuite(func() { + + crd = crdv1.CustomResourceDefinition{ + ObjectMeta: metav1.ObjectMeta{ + Name: "foo.example.com", + Labels: map[string]string{"crd": "dependency"}, + }, + } + Expect(k8sClient.Delete(context.Background(), &crd)).Should(BeNil()) + By("Deleted the custom resource definition") + + By("Tearing down the test environment") + err := testEnv.Stop() + Expect(err).ToNot(HaveOccurred()) + close(mgrclose) +}) diff --git a/pkg/controller/v1alpha2/core/scopes/healthscope/healthscope.go b/pkg/controller/v1alpha2/core/scopes/healthscope/healthscope.go index 32dbda1b..4ba983eb 100644 --- a/pkg/controller/v1alpha2/core/scopes/healthscope/healthscope.go +++ b/pkg/controller/v1alpha2/core/scopes/healthscope/healthscope.go @@ -23,6 +23,7 @@ import ( "reflect" "time" + "github.com/pkg/errors" apps "k8s.io/api/apps/v1" core "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -34,8 +35,6 @@ import ( corev1alpha2 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam" - "github.com/pkg/errors" - runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" ) diff --git a/pkg/controller/v1alpha2/core/traits/manualscalertrait/manualscalertrait_controller.go b/pkg/controller/v1alpha2/core/traits/manualscalertrait/manualscalertrait_controller.go index e8ba7858..d3b6f7dc 100644 --- a/pkg/controller/v1alpha2/core/traits/manualscalertrait/manualscalertrait_controller.go +++ b/pkg/controller/v1alpha2/core/traits/manualscalertrait/manualscalertrait_controller.go @@ -20,9 +20,6 @@ import ( "fmt" "strings" - "k8s.io/apimachinery/pkg/api/meta" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" - cpv1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" "github.com/crossplane/crossplane-runtime/pkg/event" "github.com/crossplane/crossplane-runtime/pkg/logging" @@ -42,6 +39,7 @@ import ( oamv1alpha2 "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" "github.com/crossplane/oam-kubernetes-runtime/pkg/controller" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/discoverymapper" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util" ) @@ -54,14 +52,14 @@ const ( // Setup adds a controller that reconciles ContainerizedWorkload. func Setup(mgr ctrl.Manager, args controller.Args, log logging.Logger) error { - mapper, err := apiutil.NewDiscoveryRESTMapper(mgr.GetConfig()) + dm, err := discoverymapper.New(mgr.GetConfig()) if err != nil { return err } reconciler := Reconciler{ Client: mgr.GetClient(), DiscoveryClient: *discovery.NewDiscoveryClientForConfigOrDie(mgr.GetConfig()), - mapper: mapper, + dm: dm, log: ctrl.Log.WithName("ManualScalarTrait"), record: event.NewAPIRecorder(mgr.GetEventRecorderFor("ManualScalarTrait")), Scheme: mgr.GetScheme(), @@ -73,7 +71,7 @@ func Setup(mgr ctrl.Manager, args controller.Args, log logging.Logger) error { type Reconciler struct { client.Client discovery.DiscoveryClient - mapper meta.RESTMapper + dm discoverymapper.DiscoveryMapper log logr.Logger record event.Recorder Scheme *runtime.Scheme @@ -114,7 +112,7 @@ func (r *Reconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { } // Fetch the child resources list from the corresponding workload - resources, err := util.FetchWorkloadChildResources(ctx, mLog, r, r.mapper, workload) + resources, err := util.FetchWorkloadChildResources(ctx, mLog, r, r.dm, workload) if err != nil { mLog.Error(err, "Error while fetching the workload child resources", "workload", workload.UnstructuredContent()) r.record.Event(eventObj, event.Warning(util.ErrFetchChildResources, err)) diff --git a/pkg/oam/discoverymapper/mapper.go b/pkg/oam/discoverymapper/mapper.go index abe2de3f..d2840eb8 100644 --- a/pkg/oam/discoverymapper/mapper.go +++ b/pkg/oam/discoverymapper/mapper.go @@ -8,6 +8,7 @@ import ( "k8s.io/client-go/restmapper" ) +// DiscoveryMapper is a interface for refresh and discovery resources from GVK. type DiscoveryMapper interface { GetMapper() (meta.RESTMapper, error) Refresh() (meta.RESTMapper, error) @@ -52,6 +53,7 @@ func (d *DefaultDiscoveryMapper) Refresh() (meta.RESTMapper, error) { return d.mapper, nil } +// RESTMapping will mapping resources from GVK, if not found, it will refresh from APIServer and try once again func (d *DefaultDiscoveryMapper) RESTMapping(gk schema.GroupKind, version ...string) (*meta.RESTMapping, error) { mapper, err := d.GetMapper() if err != nil { diff --git a/pkg/oam/discoverymapper/suit_test.go b/pkg/oam/discoverymapper/suit_test.go index c9e5f82d..30c46e79 100644 --- a/pkg/oam/discoverymapper/suit_test.go +++ b/pkg/oam/discoverymapper/suit_test.go @@ -8,7 +8,6 @@ import ( . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - 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" @@ -27,8 +26,6 @@ import ( var cfg *rest.Config var k8sClient client.Client var testEnv *envtest.Environment -var controllerDone chan struct{} -var routeNS corev1.Namespace var scheme = runtime.NewScheme() func TestMapper(t *testing.T) { @@ -70,7 +67,7 @@ var _ = Describe("Mapper discovery resources", func() { Expect(err).Should(BeNil()) mapper, err := dism.GetMapper() Expect(err).Should(BeNil()) - mapping, err := mapper.RESTMapping(schema.GroupKind{"apps", "Deployment"}, "v1") + mapping, err := mapper.RESTMapping(schema.GroupKind{Group: "apps", Kind: "Deployment"}, "v1") Expect(err).Should(BeNil()) Expect(mapping.Resource).Should(Equal(schema.GroupVersionResource{ Group: "apps", @@ -87,7 +84,7 @@ var _ = Describe("Mapper discovery resources", func() { mapper, err := dism.GetMapper() Expect(err).Should(BeNil()) var mapping *meta.RESTMapping - mapping, err = mapper.RESTMapping(schema.GroupKind{"", "Pod"}, "v1") + mapping, err = mapper.RESTMapping(schema.GroupKind{Group: "", Kind: "Pod"}, "v1") Expect(err).Should(BeNil()) Expect(mapping.Resource).Should(Equal(schema.GroupVersionResource{ Group: "", @@ -122,7 +119,7 @@ var _ = Describe("Mapper discovery resources", func() { Expect(k8sClient.Create(context.Background(), &crd)).Should(BeNil()) Eventually(func() error { - mapping, err = dism.RESTMapping(schema.GroupKind{"example.com", "Foo"}, "v1") + mapping, err = dism.RESTMapping(schema.GroupKind{Group: "example.com", Kind: "Foo"}, "v1") return err }, time.Second*5, time.Millisecond*500).Should(BeNil()) Expect(mapping.Resource).Should(Equal(schema.GroupVersionResource{ diff --git a/pkg/oam/mock/mapper.go b/pkg/oam/mock/mapper.go index a4392152..9b334301 100644 --- a/pkg/oam/mock/mapper.go +++ b/pkg/oam/mock/mapper.go @@ -1,89 +1,55 @@ package mock import ( + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/discoverymapper" + "k8s.io/apimachinery/pkg/api/meta" "k8s.io/apimachinery/pkg/runtime/schema" ) -var _ meta.RESTMapper = &Mapper{} - -// nolint -type KindFor func(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) - -// nolint -type KindsFor func(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) +var _ discoverymapper.DiscoveryMapper = &DiscoveryMapper{} // nolint -type ResourceFor func(input schema.GroupVersionResource) (schema.GroupVersionResource, error) +type GetMapper func() (meta.RESTMapper, error) // nolint -type ResourcesFor func(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) +type Refresh func() (meta.RESTMapper, error) // nolint type RESTMapping func(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) -// nolint -type RESTMappings func(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) - -// nolint -type ResourceSingularizer func(resource string) (singular string, err error) - -// NewMockMapper for mock -func NewMockMapper() *Mapper { - return &Mapper{ +// NewMockDiscoveryMapper for mock +func NewMockDiscoveryMapper() *DiscoveryMapper { + return &DiscoveryMapper{ MockRESTMapping: NewMockRESTMapping(""), } } -// NewMockRESTMapping for mock +// NewMockRESTMapping for unit test only func NewMockRESTMapping(resource string) RESTMapping { return func(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { - return &meta.RESTMapping{Resource: schema.GroupVersionResource{Resource: resource}}, nil + return &meta.RESTMapping{Resource: schema.GroupVersionResource{Resource: resource, Version: versions[0], Group: gk.Group}}, nil } } -// Mapper for mock -type Mapper struct { - MockKindFor KindFor - MockKindsFor KindsFor - MockResourceFor ResourceFor - MockResourcesFor ResourcesFor - MockRESTMapping RESTMapping - MockRESTMappings RESTMappings - MockResourceSingularizer ResourceSingularizer +// DiscoveryMapper for unit test only, use GetMapper and refresh will panic +type DiscoveryMapper struct { + MockGetMapper GetMapper + MockRefresh Refresh + MockRESTMapping RESTMapping } -// KindFor for mock -func (m *Mapper) KindFor(resource schema.GroupVersionResource) (schema.GroupVersionKind, error) { - return m.MockKindFor(resource) +// GetMapper for mock +func (m *DiscoveryMapper) GetMapper() (meta.RESTMapper, error) { + return m.MockGetMapper() } -// KindsFor for mock -func (m *Mapper) KindsFor(resource schema.GroupVersionResource) ([]schema.GroupVersionKind, error) { - return m.MockKindsFor(resource) -} - -// ResourceFor for mock -func (m *Mapper) ResourceFor(input schema.GroupVersionResource) (schema.GroupVersionResource, error) { - return m.MockResourceFor(input) -} - -// ResourcesFor for mock -func (m *Mapper) ResourcesFor(input schema.GroupVersionResource) ([]schema.GroupVersionResource, error) { - return m.MockResourcesFor(input) +// Refresh for mock +func (m *DiscoveryMapper) Refresh() (meta.RESTMapper, error) { + return m.MockRefresh() } // RESTMapping for mock -func (m *Mapper) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { +func (m *DiscoveryMapper) RESTMapping(gk schema.GroupKind, versions ...string) (*meta.RESTMapping, error) { return m.MockRESTMapping(gk, versions...) } - -// RESTMappings for mock -func (m *Mapper) RESTMappings(gk schema.GroupKind, versions ...string) ([]*meta.RESTMapping, error) { - return m.MockRESTMappings(gk, versions...) -} - -// ResourceSingularizer for mock -func (m *Mapper) ResourceSingularizer(resource string) (singular string, err error) { - return m.MockResourceSingularizer(resource) -} diff --git a/pkg/oam/util/helper.go b/pkg/oam/util/helper.go index 5cbcfa8a..5d485c5a 100644 --- a/pkg/oam/util/helper.go +++ b/pkg/oam/util/helper.go @@ -9,25 +9,22 @@ import ( "reflect" "time" - "k8s.io/apimachinery/pkg/runtime/schema" - - "k8s.io/apimachinery/pkg/api/meta" - + cpv1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" "github.com/davecgh/go-spew/spew" "github.com/go-logr/logr" "github.com/pkg/errors" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/runtime/schema" "k8s.io/apimachinery/pkg/types" "k8s.io/apimachinery/pkg/util/rand" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/reconcile" - cpv1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" - "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/discoverymapper" ) var ( @@ -115,11 +112,11 @@ func FetchWorkload(ctx context.Context, c client.Client, mLog logr.Logger, oamTr } // FetchScopeDefinition fetch corresponding scopeDefinition given a scope -func FetchScopeDefinition(ctx context.Context, r client.Reader, mapper meta.RESTMapper, +func FetchScopeDefinition(ctx context.Context, r client.Reader, dm discoverymapper.DiscoveryMapper, scope *unstructured.Unstructured) (*v1alpha2.ScopeDefinition, error) { // The name of the scopeDefinition CR is the CRD name of the scope // TODO(wonderflow): we haven't support scope definition label type yet. - spName, err := GetDefinitionName(mapper, scope, "") + spName, err := GetDefinitionName(dm, scope, "") if err != nil { return nil, err } @@ -134,10 +131,10 @@ func FetchScopeDefinition(ctx context.Context, r client.Reader, mapper meta.REST } // FetchTraitDefinition fetch corresponding traitDefinition given a trait -func FetchTraitDefinition(ctx context.Context, r client.Reader, mapper meta.RESTMapper, +func FetchTraitDefinition(ctx context.Context, r client.Reader, dm discoverymapper.DiscoveryMapper, trait *unstructured.Unstructured) (*v1alpha2.TraitDefinition, error) { // The name of the traitDefinition CR is the CRD name of the trait - trName, err := GetDefinitionName(mapper, trait, oam.TraitTypeLabel) + trName, err := GetDefinitionName(dm, trait, oam.TraitTypeLabel) if err != nil { return nil, err } @@ -152,10 +149,10 @@ func FetchTraitDefinition(ctx context.Context, r client.Reader, mapper meta.REST } // FetchWorkloadDefinition fetch corresponding workloadDefinition given a workload -func FetchWorkloadDefinition(ctx context.Context, r client.Reader, mapper meta.RESTMapper, +func FetchWorkloadDefinition(ctx context.Context, r client.Reader, dm discoverymapper.DiscoveryMapper, workload *unstructured.Unstructured) (*v1alpha2.WorkloadDefinition, error) { // The name of the workloadDefinition CR is the CRD name of the component - wldName, err := GetDefinitionName(mapper, workload, oam.WorkloadTypeLabel) + wldName, err := GetDefinitionName(dm, workload, oam.WorkloadTypeLabel) if err != nil { return nil, err } @@ -171,9 +168,9 @@ func FetchWorkloadDefinition(ctx context.Context, r client.Reader, mapper meta.R // FetchWorkloadChildResources fetch corresponding child resources given a workload func FetchWorkloadChildResources(ctx context.Context, mLog logr.Logger, r client.Reader, - mapper meta.RESTMapper, workload *unstructured.Unstructured) ([]*unstructured.Unstructured, error) { + dm discoverymapper.DiscoveryMapper, workload *unstructured.Unstructured) ([]*unstructured.Unstructured, error) { // Fetch the corresponding workloadDefinition CR - workloadDefinition, err := FetchWorkloadDefinition(ctx, r, mapper, workload) + workloadDefinition, err := FetchWorkloadDefinition(ctx, r, dm, workload) if err != nil { return nil, err } @@ -241,7 +238,7 @@ func PassLabelAndAnnotation(parentObj oam.Object, childObj labelAnnotationObject // the format of the definition of a resource is . // Now the definition name of a resource could also be defined as `definition.oam.dev/name` in `metadata.annotations` // typeLabel specified which Definition it is, if specified, will directly get definition from label. -func GetDefinitionName(mapper meta.RESTMapper, u *unstructured.Unstructured, typeLabel string) (string, error) { +func GetDefinitionName(dm discoverymapper.DiscoveryMapper, u *unstructured.Unstructured, typeLabel string) (string, error) { if typeLabel != "" { if labels := u.GetLabels(); labels != nil { if definitionName, ok := labels[typeLabel]; ok { @@ -253,7 +250,7 @@ func GetDefinitionName(mapper meta.RESTMapper, u *unstructured.Unstructured, typ if err != nil { return "", err } - mapping, err := mapper.RESTMapping(schema.GroupKind{Group: groupVersion.Group, Kind: u.GetKind()}, groupVersion.Version) + mapping, err := dm.RESTMapping(schema.GroupKind{Group: groupVersion.Group, Kind: u.GetKind()}, groupVersion.Version) if err != nil { return "", err } diff --git a/pkg/oam/util/helper_test.go b/pkg/oam/util/helper_test.go index 2c93fdd1..b0eddf9f 100644 --- a/pkg/oam/util/helper_test.go +++ b/pkg/oam/util/helper_test.go @@ -341,7 +341,7 @@ func TestScopeRelatedUtils(t *testing.T) { tclient := test.MockClient{ MockGet: test.NewMockGetFn(nil, tc.fields.getFunc), } - got, err := util.FetchScopeDefinition(ctx, &tclient, mock.NewMockMapper(), unstructuredScope) + got, err := util.FetchScopeDefinition(ctx, &tclient, mock.NewMockDiscoveryMapper(), unstructuredScope) t.Log(fmt.Sprint("Running test: ", name)) assert.Equal(t, tc.want.err, err) assert.Equal(t, tc.want.spd, got) @@ -434,7 +434,7 @@ func TestTraitHelper(t *testing.T) { tclient := test.MockClient{ MockGet: test.NewMockGetFn(nil, tc.fields.getFunc), } - got, err := util.FetchTraitDefinition(ctx, &tclient, mock.NewMockMapper(), unstructuredTrait) + got, err := util.FetchTraitDefinition(ctx, &tclient, mock.NewMockDiscoveryMapper(), unstructuredTrait) t.Log(fmt.Sprint("Running test: ", name)) assert.Equal(t, tc.want.err, err) assert.Equal(t, tc.want.td, got) @@ -521,7 +521,7 @@ func TestUtils(t *testing.T) { tclient := test.MockClient{ MockGet: test.NewMockGetFn(nil, tc.fields.getFunc), } - got, err := util.FetchWorkloadDefinition(ctx, &tclient, mock.NewMockMapper(), unstructuredWorkload) + got, err := util.FetchWorkloadDefinition(ctx, &tclient, mock.NewMockDiscoveryMapper(), unstructuredWorkload) t.Log(fmt.Sprint("Running test: ", name)) assert.Equal(t, tc.want.err, err) @@ -705,7 +705,7 @@ func TestChildResources(t *testing.T) { MockGet: test.NewMockGetFn(nil, tc.fields.getFunc), MockList: test.NewMockListFn(nil, tc.fields.listFunc), } - got, err := util.FetchWorkloadChildResources(ctx, log, &tclient, mock.NewMockMapper(), unstructuredWorkload) + got, err := util.FetchWorkloadChildResources(ctx, log, &tclient, mock.NewMockDiscoveryMapper(), unstructuredWorkload) t.Log(fmt.Sprint("Running test: ", name)) assert.Equal(t, tc.want.err, err) assert.Equal(t, tc.want.crks, got) @@ -763,7 +763,7 @@ func TestUnstructured(t *testing.T) { }, } for name, ti := range tests { - mapper := mock.NewMockMapper() + mapper := mock.NewMockDiscoveryMapper() mapper.MockRESTMapping = mock.NewMockRESTMapping(ti.resource) got, err := util.GetDefinitionName(mapper, ti.u, ti.typeLabel) assert.NoError(t, err) diff --git a/pkg/webhook/v1alpha2/applicationconfiguration/handler_test.go b/pkg/webhook/v1alpha2/applicationconfiguration/handler_test.go index 258fe24d..069f5a04 100644 --- a/pkg/webhook/v1alpha2/applicationconfiguration/handler_test.go +++ b/pkg/webhook/v1alpha2/applicationconfiguration/handler_test.go @@ -4,8 +4,6 @@ import ( "context" "fmt" - "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/mock" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -22,6 +20,7 @@ import ( "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/mock" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util" ) @@ -191,7 +190,7 @@ var _ = Describe("ApplicationConfiguration Admission controller Test", func() { }) It("Test validating handler", func() { - mapper := mock.NewMockMapper() + mapper := mock.NewMockDiscoveryMapper() var handler admission.Handler = &ValidatingHandler{Mapper: mapper} decoderInjector := handler.(admission.DecoderInjector) decoderInjector.InjectDecoder(decoder) diff --git a/pkg/webhook/v1alpha2/applicationconfiguration/helper.go b/pkg/webhook/v1alpha2/applicationconfiguration/helper.go index 193ba385..5aa60909 100644 --- a/pkg/webhook/v1alpha2/applicationconfiguration/helper.go +++ b/pkg/webhook/v1alpha2/applicationconfiguration/helper.go @@ -5,13 +5,12 @@ import ( "encoding/json" "strings" - "k8s.io/apimachinery/pkg/api/meta" - "github.com/pkg/errors" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "sigs.k8s.io/controller-runtime/pkg/client" "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/discoverymapper" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util" ) @@ -21,7 +20,7 @@ const ( ) // checkComponentVersionEnabled check whethter a component is versioning mechanism enabled -func checkComponentVersionEnabled(ctx context.Context, client client.Reader, mapper meta.RESTMapper, +func checkComponentVersionEnabled(ctx context.Context, client client.Reader, dm discoverymapper.DiscoveryMapper, acc *v1alpha2.ApplicationConfigurationComponent) (bool, error) { if acc.RevisionName != "" { return true, nil @@ -31,7 +30,7 @@ func checkComponentVersionEnabled(ctx context.Context, client client.Reader, map if err := json.Unmarshal(ct.Trait.Raw, ut); err != nil { return false, errors.Wrap(err, errUnmarshalTrait) } - td, err := util.FetchTraitDefinition(ctx, client, mapper, ut) + td, err := util.FetchTraitDefinition(ctx, client, dm, ut) if err != nil { return false, errors.Wrapf(err, errFmtGetTraitDefinition, ut.GetAPIVersion(), ut.GetKind(), ut.GetName()) } diff --git a/pkg/webhook/v1alpha2/applicationconfiguration/helper_test.go b/pkg/webhook/v1alpha2/applicationconfiguration/helper_test.go index 98b67dc4..3234c119 100644 --- a/pkg/webhook/v1alpha2/applicationconfiguration/helper_test.go +++ b/pkg/webhook/v1alpha2/applicationconfiguration/helper_test.go @@ -5,8 +5,6 @@ import ( "fmt" "testing" - "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/mock" - "github.com/crossplane/crossplane-runtime/pkg/test" "github.com/stretchr/testify/assert" @@ -17,6 +15,7 @@ import ( "k8s.io/apimachinery/pkg/util/intstr" "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/mock" ) func TestCheckComponentVersionEnabled(t *testing.T) { @@ -100,7 +99,7 @@ func TestCheckComponentVersionEnabled(t *testing.T) { result: false, }, } - mapper := mock.NewMockMapper() + mapper := mock.NewMockDiscoveryMapper() for _, tv := range tests { func(t *testing.T) { diff --git a/pkg/webhook/v1alpha2/applicationconfiguration/validating_handler.go b/pkg/webhook/v1alpha2/applicationconfiguration/validating_handler.go index b7845f30..cbb13daa 100644 --- a/pkg/webhook/v1alpha2/applicationconfiguration/validating_handler.go +++ b/pkg/webhook/v1alpha2/applicationconfiguration/validating_handler.go @@ -6,19 +6,14 @@ import ( "fmt" "net/http" - "sigs.k8s.io/controller-runtime/pkg/client/apiutil" - - "k8s.io/apimachinery/pkg/api/meta" - - "k8s.io/apimachinery/pkg/util/validation/field" - - "github.com/crossplane/crossplane-runtime/pkg/fieldpath" - "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" + "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/discoverymapper" "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util" + "github.com/crossplane/crossplane-runtime/pkg/fieldpath" admissionv1beta1 "k8s.io/api/admission/v1beta1" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" + "k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/klog" "sigs.k8s.io/controller-runtime/pkg/client" "sigs.k8s.io/controller-runtime/pkg/manager" @@ -43,7 +38,7 @@ var appConfigResource = v1alpha2.SchemeGroupVersion.WithResource("applicationcon // ValidatingHandler handles CloneSet type ValidatingHandler struct { Client client.Client - Mapper meta.RESTMapper + Mapper discoverymapper.DiscoveryMapper // Decoder decodes objects Decoder *admission.Decoder @@ -131,11 +126,11 @@ func checkRevisionName(appConfig *v1alpha2.ApplicationConfiguration) (bool, stri } // checkWorkloadNameForVersioning check whether versioning-enabled component workload name is empty -func checkWorkloadNameForVersioning(ctx context.Context, client client.Reader, mapper meta.RESTMapper, +func checkWorkloadNameForVersioning(ctx context.Context, client client.Reader, dm discoverymapper.DiscoveryMapper, appConfig *v1alpha2.ApplicationConfiguration) (bool, string) { for _, v := range appConfig.Spec.Components { acc := v - vEnabled, err := checkComponentVersionEnabled(ctx, client, mapper, &acc) + vEnabled, err := checkComponentVersionEnabled(ctx, client, dm, &acc) if err != nil { return false, fmt.Sprintf(errFmtCheckWorkloadName, err.Error()) } @@ -184,7 +179,7 @@ func (h *ValidatingHandler) InjectDecoder(d *admission.Decoder) error { // RegisterValidatingHandler will register application configuration validation to webhook func RegisterValidatingHandler(mgr manager.Manager) error { server := mgr.GetWebhookServer() - mapper, err := apiutil.NewDiscoveryRESTMapper(mgr.GetConfig()) + mapper, err := discoverymapper.New(mgr.GetConfig()) if err != nil { return err } diff --git a/pkg/webhook/v1alpha2/applicationconfiguration/validating_handler_test.go b/pkg/webhook/v1alpha2/applicationconfiguration/validating_handler_test.go index 930d38ad..8bd09dfd 100644 --- a/pkg/webhook/v1alpha2/applicationconfiguration/validating_handler_test.go +++ b/pkg/webhook/v1alpha2/applicationconfiguration/validating_handler_test.go @@ -152,7 +152,7 @@ func TestCheckWorkloadNameForVersioning(t *testing.T) { Name: tName, }}) - mapper := mock.NewMockMapper() + mapper := mock.NewMockDiscoveryMapper() tests := []struct { caseName string diff --git a/test/e2e-test/appconfig_dependency_test.go b/test/e2e-test/appconfig_dependency_test.go deleted file mode 100644 index 15d177a5..00000000 --- a/test/e2e-test/appconfig_dependency_test.go +++ /dev/null @@ -1,592 +0,0 @@ -package controllers_test - -import ( - "context" - "time" - - . "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/apis/meta/v1/unstructured" - "k8s.io/apimachinery/pkg/runtime" - "sigs.k8s.io/controller-runtime/pkg/client" - logf "sigs.k8s.io/controller-runtime/pkg/log" - - "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1" - - "github.com/crossplane/oam-kubernetes-runtime/apis/core/v1alpha2" - "github.com/crossplane/oam-kubernetes-runtime/pkg/oam/util" -) - -var _ = Describe("Resource Dependency in an ApplicationConfiguration", func() { - ctx := context.Background() - namespace := "appconfig-dependency-test" - var ns corev1.Namespace - var wd v1alpha2.WorkloadDefinition - var td v1alpha2.TraitDefinition - tempFoo := &unstructured.Unstructured{} - tempFoo.SetAPIVersion("example.com/v1") - tempFoo.SetKind("Foo") - tempFoo.SetNamespace(namespace) - outName := "data-output" - out := tempFoo.DeepCopy() - out.SetName(outName) - inName := "data-input" - in := tempFoo.DeepCopy() - in.SetName(inName) - componentOutName := "component-out" - componentInName := "component-in" - BeforeEach(func() { - ns = corev1.Namespace{ - ObjectMeta: metav1.ObjectMeta{ - Name: namespace, - }, - } - logf.Log.Info("Start to run a test, clean up previous resources") - // delete the namespace with all its resources - Eventually( - // gomega has a bug that can't take nil as the actual input, so has to make it a func - func() error { - return k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground)) - }, - time.Second*30, time.Millisecond*500).Should(SatisfyAny(BeNil(), &util.NotFoundMatcher{})) - - logf.Log.Info("make sure all the resources are removed") - objectKey := client.ObjectKey{ - Name: namespace, - } - res := &corev1.Namespace{} - Eventually( - // gomega has a bug that can't take nil as the actual input, so has to make it a func - func() error { - return k8sClient.Get(ctx, objectKey, res) - }, - time.Second*30, time.Millisecond*500).Should(&util.NotFoundMatcher{}) - // recreate the namespace for testing - Eventually( - func() error { - return k8sClient.Create(ctx, &ns) - }, - time.Second*3, time.Millisecond*300).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - wd = v1alpha2.WorkloadDefinition{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo.example.com", - }, - Spec: v1alpha2.WorkloadDefinitionSpec{ - Reference: v1alpha2.DefinitionReference{ - Name: "foo.example.com", - }, - }, - } - td = v1alpha2.TraitDefinition{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foos.example.com", - }, - Spec: v1alpha2.TraitDefinitionSpec{ - Reference: v1alpha2.DefinitionReference{ - Name: "foos.example.com", - }, - }, - } - logf.Log.Info("Creating workload definition") - // For some reason, WorkloadDefinition is created as a Cluster scope object - Expect(k8sClient.Create(ctx, &wd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - logf.Log.Info("Creating trait definition") - // For some reason, TraitDefinition is created as a Cluster scope object - Expect(k8sClient.Create(ctx, &td)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - // Create a component for data outputs - compOut := v1alpha2.Component{ - ObjectMeta: metav1.ObjectMeta{ - Name: componentOutName, - Namespace: namespace, - }, - Spec: v1alpha2.ComponentSpec{ - Workload: runtime.RawExtension{ - Object: out, - }, - }, - } - Expect(k8sClient.Create(ctx, &compOut)).Should(BeNil()) - logf.Log.Info("Creating component that outputs data", "Name", compOut.Name, "Namespace", compOut.Namespace) - // Create a component for data inputs - compIn := v1alpha2.Component{ - ObjectMeta: metav1.ObjectMeta{ - Name: componentInName, - Namespace: namespace, - }, - Spec: v1alpha2.ComponentSpec{ - Workload: runtime.RawExtension{ - Object: in, - }, - }, - } - Expect(k8sClient.Create(ctx, &compIn)).Should(BeNil()) - logf.Log.Info("Creating component that inputs data", "Name", compIn.Name, "Namespace", compIn.Namespace) - }) - AfterEach(func() { - logf.Log.Info("Clean up resources") - // Delete the WorkloadDefinition and TraitDefinition - Expect(k8sClient.Delete(ctx, &wd)).Should(BeNil()) - Expect(k8sClient.Delete(ctx, &td)).Should(BeNil()) - // delete the namespace with all its resources - Expect(k8sClient.Delete(ctx, &ns, client.PropagationPolicy(metav1.DeletePropagationForeground))).Should(BeNil()) - }) - - // common function for verification - verify := func(appConfigName, reason string) { - // Verification before satisfying dependency - By("Checking that resource which accepts data isn't created yet") - inFooKey := client.ObjectKey{ - Name: inName, - Namespace: namespace, - } - inFoo := tempFoo.DeepCopy() - logf.Log.Info("Checking on resource that inputs data", "Key", inFooKey) - Eventually( - func() error { - return k8sClient.Get(ctx, inFooKey, inFoo) - }, - time.Second*60, time.Second*2).Should(&util.NotFoundMatcher{}) - By("Checking that resource which provides data is created") - outFooKey := client.ObjectKey{ - Name: outName, - Namespace: namespace, - } - outFoo := tempFoo.DeepCopy() - logf.Log.Info("Checking on resource that outputs data", "Key", outFoo) - Eventually( - func() error { - return k8sClient.Get(ctx, outFooKey, outFoo) - }, - time.Second*60, time.Second*2).Should(BeNil()) - By("Verify the appconfig's dependency is unsatisfied") - appconfigKey := client.ObjectKey{ - Name: appConfigName, - Namespace: namespace, - } - appconfig := &v1alpha2.ApplicationConfiguration{} - depStatus := v1alpha2.DependencyStatus{ - Unsatisfied: []v1alpha2.UnstaifiedDependency{ - { - Reason: reason, - From: v1alpha2.DependencyFromObject{ - TypedReference: v1alpha1.TypedReference{ - APIVersion: tempFoo.GetAPIVersion(), - Name: outName, - Kind: tempFoo.GetKind(), - }, - FieldPath: "status.key", - }, - To: v1alpha2.DependencyToObject{ - TypedReference: v1alpha1.TypedReference{ - APIVersion: tempFoo.GetAPIVersion(), - Name: inName, - Kind: tempFoo.GetKind(), - }, - FieldPaths: []string{ - "spec.key", - }, - }, - }, - }, - } - logf.Log.Info("Checking on appconfig", "Key", appconfigKey) - Eventually( - func() v1alpha2.DependencyStatus { - k8sClient.Get(ctx, appconfigKey, appconfig) - return appconfig.Status.Dependency - }, - time.Second*120, time.Second*2).Should(Equal(depStatus)) - // fill value to fieldPath - err := unstructured.SetNestedField(outFoo.Object, "test", "status", "key") - Expect(err).Should(BeNil()) - Expect(k8sClient.Update(ctx, outFoo)).Should(Succeed()) - // Verification after satisfying dependency - By("Checking that resource which accepts data is created now") - logf.Log.Info("Checking on resource that inputs data", "Key", inFooKey) - Eventually( - func() error { - return k8sClient.Get(ctx, inFooKey, inFoo) - }, - time.Second*120, time.Second*2).Should(BeNil()) - By("Verify the appconfig's dependency is satisfied") - appconfig = &v1alpha2.ApplicationConfiguration{} - logf.Log.Info("Checking on appconfig", "Key", appconfigKey) - Eventually( - func() []v1alpha2.UnstaifiedDependency { - k8sClient.Get(ctx, appconfigKey, appconfig) - return appconfig.Status.Dependency.Unsatisfied - }, - time.Second*300, time.Second*2).Should(BeNil()) - } - - It("trait depends on another trait", func() { - label := map[string]string{"trait": "trait"} - // Define a workload - wl := tempFoo.DeepCopy() - wl.SetName("workload") - // Create a component - componentName := "component" - comp := v1alpha2.Component{ - ObjectMeta: metav1.ObjectMeta{ - Name: componentName, - Namespace: namespace, - Labels: label, - }, - Spec: v1alpha2.ComponentSpec{ - Workload: runtime.RawExtension{ - Object: wl, - }, - }, - } - Expect(k8sClient.Create(ctx, &comp)).Should(BeNil()) - logf.Log.Info("Creating component", "Name", comp.Name, "Namespace", comp.Namespace) - // Create application configuration - appConfigName := "appconfig-trait-trait" - appConfig := v1alpha2.ApplicationConfiguration{ - ObjectMeta: metav1.ObjectMeta{ - Name: appConfigName, - Namespace: namespace, - Labels: label, - }, - Spec: v1alpha2.ApplicationConfigurationSpec{ - Components: []v1alpha2.ApplicationConfigurationComponent{ - { - ComponentName: componentName, - Traits: []v1alpha2.ComponentTrait{ - { - Trait: runtime.RawExtension{ - Object: out, - }, - DataOutputs: []v1alpha2.DataOutput{ - { - Name: "trait-trait", - FieldPath: "status.key", - }, - }, - }, - { - Trait: runtime.RawExtension{ - Object: in, - }, - DataInputs: []v1alpha2.DataInput{ - { - ValueFrom: v1alpha2.DataInputValueFrom{ - DataOutputName: "trait-trait", - }, - ToFieldPaths: []string{"spec.key"}, - }, - }, - }, - }, - }, - }, - }, - } - logf.Log.Info("Creating application config", "Name", appConfig.Name, "Namespace", appConfig.Namespace) - Expect(k8sClient.Create(ctx, &appConfig)).Should(BeNil()) - verify(appConfigName, "status.key not found in object") - }) - - It("component depends on another component", func() { - label := map[string]string{"component": "component"} - // Create application configuration - appConfigName := "appconfig-comp-comp" - appConfig := v1alpha2.ApplicationConfiguration{ - ObjectMeta: metav1.ObjectMeta{ - Name: appConfigName, - Namespace: namespace, - Labels: label, - }, - Spec: v1alpha2.ApplicationConfigurationSpec{ - Components: []v1alpha2.ApplicationConfigurationComponent{ - { - ComponentName: componentOutName, - DataOutputs: []v1alpha2.DataOutput{ - { - Name: "comp-comp", - FieldPath: "status.key", - }, - }, - }, - { - ComponentName: componentInName, - DataInputs: []v1alpha2.DataInput{ - { - ValueFrom: v1alpha2.DataInputValueFrom{ - DataOutputName: "comp-comp", - }, - ToFieldPaths: []string{"spec.key"}, - }, - }, - }, - }, - }, - } - logf.Log.Info("Creating application config", "Name", appConfig.Name, "Namespace", appConfig.Namespace) - Expect(k8sClient.Create(ctx, &appConfig)).Should(BeNil()) - verify(appConfigName, "status.key not found in object") - }) - - It("component depends on trait", func() { - label := map[string]string{"trait": "component"} - // Create application configuration - appConfigName := "appconfig-trait-comp" - appConfig := v1alpha2.ApplicationConfiguration{ - ObjectMeta: metav1.ObjectMeta{ - Name: appConfigName, - Namespace: namespace, - Labels: label, - }, - Spec: v1alpha2.ApplicationConfigurationSpec{ - Components: []v1alpha2.ApplicationConfigurationComponent{ - { - ComponentName: componentInName, - DataInputs: []v1alpha2.DataInput{ - { - ValueFrom: v1alpha2.DataInputValueFrom{ - DataOutputName: "trait-comp", - }, - ToFieldPaths: []string{"spec.key"}, - }, - }, - Traits: []v1alpha2.ComponentTrait{ - { - Trait: runtime.RawExtension{ - Object: out, - }, - DataOutputs: []v1alpha2.DataOutput{ - { - Name: "trait-comp", - FieldPath: "status.key", - }, - }, - }, - }, - }, - }, - }, - } - logf.Log.Info("Creating application config", "Name", appConfig.Name, "Namespace", appConfig.Namespace) - Expect(k8sClient.Create(ctx, &appConfig)).Should(BeNil()) - verify(appConfigName, "status.key not found in object") - }) - - It("trait depends on component", func() { - label := map[string]string{"component": "trait"} - // Create application configuration - appConfigName := "appconfig-comp-trait" - appConfig := v1alpha2.ApplicationConfiguration{ - ObjectMeta: metav1.ObjectMeta{ - Name: appConfigName, - Namespace: namespace, - Labels: label, - }, - Spec: v1alpha2.ApplicationConfigurationSpec{ - Components: []v1alpha2.ApplicationConfigurationComponent{ - { - ComponentName: componentOutName, - DataOutputs: []v1alpha2.DataOutput{ - { - Name: "comp-trait", - FieldPath: "status.key", - }, - }, - Traits: []v1alpha2.ComponentTrait{ - { - Trait: runtime.RawExtension{ - Object: in, - }, - DataInputs: []v1alpha2.DataInput{ - { - ValueFrom: v1alpha2.DataInputValueFrom{ - DataOutputName: "comp-trait", - }, - ToFieldPaths: []string{"spec.key"}, - }, - }, - }, - }, - }, - }, - }, - } - logf.Log.Info("Creating application config", "Name", appConfig.Name, "Namespace", appConfig.Namespace) - Expect(k8sClient.Create(ctx, &appConfig)).Should(BeNil()) - verify(appConfigName, "status.key not found in object") - }) - - It("component depends on trait with updated condition", func() { - label := map[string]string{"trait": "component", "app-hash": "hash-v1"} - // Create application configuration - appConfigName := "appconfig-trait-comp" - appConfig := v1alpha2.ApplicationConfiguration{ - ObjectMeta: metav1.ObjectMeta{ - Name: appConfigName, - Namespace: namespace, - Labels: label, - }, - Spec: v1alpha2.ApplicationConfigurationSpec{ - Components: []v1alpha2.ApplicationConfigurationComponent{ - { - ComponentName: componentInName, - DataInputs: []v1alpha2.DataInput{ - { - ValueFrom: v1alpha2.DataInputValueFrom{ - DataOutputName: "trait-comp", - }, - ToFieldPaths: []string{"spec.key"}, - }, - }, - Traits: []v1alpha2.ComponentTrait{ - { - Trait: runtime.RawExtension{ - Object: out, - }, - DataOutputs: []v1alpha2.DataOutput{ - { - Name: "trait-comp", - FieldPath: "status.key", - Conditions: []v1alpha2.ConditionRequirement{ - { - Operator: v1alpha2.ConditionEqual, - ValueFrom: v1alpha2.ValueFrom{FieldPath: "metadata.labels.app-hash"}, - FieldPath: "status.app-hash", - }, - }, - }, - }, - }, - }, - }, - }, - }, - } - logf.Log.Info("Creating application config", "Name", appConfig.Name, "Namespace", appConfig.Namespace) - Expect(k8sClient.Create(ctx, &appConfig)).Should(BeNil()) - By("Checking that resource which accepts data isn't created yet") - inFooKey := client.ObjectKey{ - Name: inName, - Namespace: namespace, - } - inFoo := tempFoo.DeepCopy() - logf.Log.Info("Checking on resource that inputs data", "Key", inFooKey) - Eventually( - func() error { - return k8sClient.Get(ctx, inFooKey, inFoo) - }, - time.Second*60, time.Second*2).Should(&util.NotFoundMatcher{}) - - By("Checking that resource which provides data is created") - // Originally the trait has value in `status.key`, but the hash label is old - outFooKey := client.ObjectKey{ - Name: outName, - Namespace: namespace, - } - outFoo := tempFoo.DeepCopy() - Eventually( - func() error { - return k8sClient.Get(ctx, outFooKey, outFoo) - }, - time.Second*60, time.Second*2).Should(BeNil()) - err := unstructured.SetNestedField(outFoo.Object, "test", "status", "key") - Expect(err).Should(BeNil()) - err = unstructured.SetNestedField(outFoo.Object, "hash-v1", "status", "app-hash") - Expect(err).Should(BeNil()) - Expect(k8sClient.Update(ctx, outFoo)).Should(Succeed()) - - appconfigKey := client.ObjectKey{ - Name: appConfigName, - Namespace: namespace, - } - newAppConfig := &v1alpha2.ApplicationConfiguration{} - - // Verification after satisfying dependency - By("Verify the appconfig's dependency is satisfied") - newAppConfig = &v1alpha2.ApplicationConfiguration{} - logf.Log.Info("Checking on appconfig", "Key", appconfigKey) - Eventually( - func() []v1alpha2.UnstaifiedDependency { - var tempApp = &v1alpha2.ApplicationConfiguration{} - k8sClient.Get(ctx, appconfigKey, tempApp) - tempApp.DeepCopyInto(newAppConfig) - return tempApp.Status.Dependency.Unsatisfied - }, - time.Second*80, time.Second*2).Should(BeNil()) - By("Checking that resource which accepts data is created now") - logf.Log.Info("Checking on resource that inputs data", "Key", inFooKey) - Eventually( - func() error { - return k8sClient.Get(ctx, inFooKey, inFoo) - }, - time.Second*80, time.Second*2).Should(BeNil()) - - newAppConfig.Labels["app-hash"] = "hash-v2" - Expect(k8sClient.Update(ctx, newAppConfig)).Should(BeNil()) - - By("Verify the appconfig's dependency should be unsatisfied, because requirementCondition valueFrom not match") - - depStatus := v1alpha2.DependencyStatus{ - Unsatisfied: []v1alpha2.UnstaifiedDependency{ - { - Reason: "got(hash-v1) expected to be hash-v2", - From: v1alpha2.DependencyFromObject{ - TypedReference: v1alpha1.TypedReference{ - APIVersion: tempFoo.GetAPIVersion(), - Name: outName, - Kind: tempFoo.GetKind(), - }, - FieldPath: "status.key", - }, - To: v1alpha2.DependencyToObject{ - TypedReference: v1alpha1.TypedReference{ - APIVersion: tempFoo.GetAPIVersion(), - Name: inName, - Kind: tempFoo.GetKind(), - }, - FieldPaths: []string{ - "spec.key", - }, - }, - }, - }, - } - logf.Log.Info("Checking on appconfig", "Key", appconfigKey) - Eventually( - func() v1alpha2.DependencyStatus { - k8sClient.Get(ctx, appconfigKey, newAppConfig) - return newAppConfig.Status.Dependency - }, - time.Second*60, time.Second*2).Should(Equal(depStatus)) - - // Update trait object - k8sClient.Get(ctx, outFooKey, outFoo) // Get the latest before update - err = unstructured.SetNestedField(outFoo.Object, "test-new", "status", "key") - Expect(err).Should(BeNil()) - err = unstructured.SetNestedField(outFoo.Object, "hash-v2", "status", "app-hash") - Expect(err).Should(BeNil()) - Expect(k8sClient.Update(ctx, outFoo)).Should(Succeed()) - - // Verification after satisfying dependency - By("Checking that resource which accepts data is updated now") - logf.Log.Info("Checking on resource that inputs data", "Key", inFooKey) - Eventually( - func() string { - k8sClient.Get(ctx, inFooKey, inFoo) - outdata, _, _ := unstructured.NestedString(inFoo.Object, "spec", "key") - return outdata - }, - time.Second*80, time.Second*2).Should(Equal("test-new")) - By("Verify the appconfig's dependency is satisfied") - logf.Log.Info("Checking on appconfig", "Key", appconfigKey) - Eventually( - func() []v1alpha2.UnstaifiedDependency { - tempAppConfig := &v1alpha2.ApplicationConfiguration{} - k8sClient.Get(ctx, appconfigKey, tempAppConfig) - return tempAppConfig.Status.Dependency.Unsatisfied - }, - time.Second*80, time.Second*2).Should(BeNil()) - }) -}) diff --git a/test/e2e-test/appconfig_finalizer_test.go b/test/e2e-test/appconfig_finalizer_test.go index d5f6ad2b..e62fdf40 100644 --- a/test/e2e-test/appconfig_finalizer_test.go +++ b/test/e2e-test/appconfig_finalizer_test.go @@ -101,7 +101,7 @@ var _ = Describe("Finalizer for HealthScope in ApplicationConfiguration", func() func() error { return k8sClient.Get(ctx, objectKey, res) }, - time.Second*60, time.Millisecond*500).Should(&util.NotFoundMatcher{}) + time.Second*120, time.Millisecond*500).Should(&util.NotFoundMatcher{}) Eventually( func() error { return k8sClient.Create(ctx, &ns) diff --git a/test/e2e-test/component_version_test.go b/test/e2e-test/component_version_test.go index c0d852e4..39510e2d 100644 --- a/test/e2e-test/component_version_test.go +++ b/test/e2e-test/component_version_test.go @@ -134,7 +134,7 @@ var _ = Describe("Versioning mechanism of components", func() { func() error { return k8sClient.Get(ctx, objectKey, res) }, - time.Second*60, time.Millisecond*500).Should(&util.NotFoundMatcher{}) + time.Second*120, time.Millisecond*500).Should(&util.NotFoundMatcher{}) Eventually( func() error { return k8sClient.Create(ctx, &ns) @@ -334,7 +334,7 @@ var _ = Describe("Versioning mechanism of components", func() { k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: componentName}, &comp1) return comp1.Status.LatestRevision }, - time.Second*30, time.Millisecond*500).ShouldNot(BeNil()) + time.Second*120, time.Millisecond*500).ShouldNot(BeNil()) revisionNameV1 := comp1.Status.LatestRevision.Name @@ -365,7 +365,7 @@ var _ = Describe("Versioning mechanism of components", func() { } return nil }, - time.Second*30, time.Millisecond*500).ShouldNot(BeNil()) + time.Second*120, time.Millisecond*500).ShouldNot(BeNil()) revisionNameV2 := comp2.Status.LatestRevision.Name @@ -377,7 +377,7 @@ var _ = Describe("Versioning mechanism of components", func() { w2.SetKind("Bar") return k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: revisionNameV2}, &w2) }, - time.Second*15, time.Millisecond*500).Should(BeNil()) + time.Second*60, time.Millisecond*500).Should(BeNil()) k2, _, _ := unstructured.NestedString(w2.Object, "spec", "key") Expect(k2).Should(BeEquivalentTo("v2"), fmt.Sprintf("%v", w2.Object)) @@ -436,7 +436,7 @@ var _ = Describe("Versioning mechanism of components", func() { w1.SetKind("Bar") return k8sClient.Get(ctx, client.ObjectKey{Namespace: namespace, Name: componentName}, &w1) }, - time.Second*15, time.Millisecond*500).Should(BeNil()) + time.Second*60, time.Millisecond*500).Should(BeNil()) k1, _, _ := unstructured.NestedString(w1.Object, "spec", "key") Expect(k1).Should(BeEquivalentTo("v1"), fmt.Sprintf("%v", w1.Object)) @@ -461,7 +461,7 @@ var _ = Describe("Versioning mechanism of components", func() { k2, _, _ := unstructured.NestedString(w2.Object, "spec", "key") return k2 }, - time.Second*15, time.Millisecond*500).Should(BeEquivalentTo("v2")) + time.Second*120, time.Millisecond*500).Should(BeEquivalentTo("v2")) By("Check AppConfig status") Eventually( diff --git a/test/e2e-test/containerized_workload_test.go b/test/e2e-test/containerized_workload_test.go index 8f4c2b39..ea49e56f 100644 --- a/test/e2e-test/containerized_workload_test.go +++ b/test/e2e-test/containerized_workload_test.go @@ -60,7 +60,7 @@ var _ = Describe("ContainerizedWorkload", func() { func() error { return k8sClient.Get(ctx, objectKey, res) }, - time.Second*30, time.Millisecond*500).Should(&util.NotFoundMatcher{}) + time.Second*120, time.Millisecond*500).Should(&util.NotFoundMatcher{}) // recreate it Eventually( func() error { diff --git a/test/e2e-test/health_scope_test.go b/test/e2e-test/health_scope_test.go index 8906f832..143cbda4 100644 --- a/test/e2e-test/health_scope_test.go +++ b/test/e2e-test/health_scope_test.go @@ -49,7 +49,7 @@ var _ = Describe("HealthScope", func() { func() error { return k8sClient.Get(ctx, objectKey, res) }, - time.Second*30, time.Millisecond*500).Should(&util.NotFoundMatcher{}) + time.Second*120, time.Millisecond*500).Should(&util.NotFoundMatcher{}) // recreate it Eventually( func() error { diff --git a/test/e2e-test/kubernetes_workload_test.go b/test/e2e-test/kubernetes_workload_test.go index 7201ee86..9395e7f3 100644 --- a/test/e2e-test/kubernetes_workload_test.go +++ b/test/e2e-test/kubernetes_workload_test.go @@ -43,7 +43,7 @@ var _ = Describe("Test kubernetes native workloads", func() { func() error { return k8sClient.Get(ctx, objectKey, res) }, - time.Second*30, time.Millisecond*500).Should(&util.NotFoundMatcher{}) + time.Second*120, time.Millisecond*500).Should(&util.NotFoundMatcher{}) // recreate it Eventually( func() error { diff --git a/test/e2e-test/suite_test.go b/test/e2e-test/suite_test.go index 715793cc..d7d9be5b 100644 --- a/test/e2e-test/suite_test.go +++ b/test/e2e-test/suite_test.go @@ -197,52 +197,6 @@ var _ = BeforeSuite(func(done Done) { } Expect(k8sClient.Create(context.Background(), &adminRoleBinding)).Should(BeNil()) By("Created cluster role binding for the test service account") - // Create a crd for appconfig dependency test - crd = crdv1.CustomResourceDefinition{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo.example.com", - Labels: map[string]string{"crd": "dependency"}, - }, - Spec: crdv1.CustomResourceDefinitionSpec{ - Group: "example.com", - Names: crdv1.CustomResourceDefinitionNames{ - Kind: "Foo", - ListKind: "FooList", - Plural: "foo", - Singular: "foo", - }, - Versions: []crdv1.CustomResourceDefinitionVersion{ - { - Name: "v1", - Served: true, - Storage: true, - Schema: &crdv1.CustomResourceValidation{ - OpenAPIV3Schema: &crdv1.JSONSchemaProps{ - Type: "object", - Properties: map[string]crdv1.JSONSchemaProps{ - "spec": { - Type: "object", - Properties: map[string]crdv1.JSONSchemaProps{ - "key": {Type: "string"}, - }, - }, - "status": { - Type: "object", - Properties: map[string]crdv1.JSONSchemaProps{ - "key": {Type: "string"}, - "app-hash": {Type: "string"}, - }, - }, - }, - }, - }, - }, - }, - Scope: crdv1.NamespaceScoped, - }, - } - Expect(k8sClient.Create(context.Background(), &crd)).Should(SatisfyAny(BeNil(), &util.AlreadyExistMatcher{})) - By("Created a crd for appconfig dependency test") crd = crdv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{ @@ -301,22 +255,6 @@ var _ = AfterSuite(func() { } Expect(k8sClient.Delete(context.Background(), &adminRoleBinding)).Should(BeNil()) By("Deleted the cluster role binding") - manualscalertrait = v1alpha2.TraitDefinition{ - ObjectMeta: metav1.ObjectMeta{ - Name: "manualscalertraits.core.oam.dev", - Labels: map[string]string{"trait": "manualscalertrait"}, - }, - } - Expect(k8sClient.Delete(context.Background(), &manualscalertrait)).Should(BeNil()) - Expect(k8sClient.Delete(context.Background(), &extendedmanualscalertrait)).Should(BeNil()) - By("Deleted the manual scalertrait definition") - crd = crdv1.CustomResourceDefinition{ - ObjectMeta: metav1.ObjectMeta{ - Name: "foo.example.com", - Labels: map[string]string{"crd": "dependency"}, - } - } - Expect(k8sClient.Delete(context.Background(), &crd)).Should(BeNil()) crd = crdv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{ @@ -327,18 +265,19 @@ var _ = AfterSuite(func() { Expect(k8sClient.Delete(context.Background(), &crd)).Should(BeNil()) By("Deleted the custom resource definition") - td := v1alpha2.TraitDefinition{ + crd = crdv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "bars.example.com", + Name: "workloaddefinitions.core.oam.dev", }, } - k8sClient.Delete(context.Background(), &td) + Expect(k8sClient.Delete(context.Background(), &crd)).Should(BeNil()) + By("Deleted the workloaddefinitions CRD") - wd := v1alpha2.WorkloadDefinition{ + crd = crdv1.CustomResourceDefinition{ ObjectMeta: metav1.ObjectMeta{ - Name: "bars.example.com", + Name: "traitdefinitions.core.oam.dev", }, } - k8sClient.Delete(context.Background(), &wd) - + Expect(k8sClient.Delete(context.Background(), &crd)).Should(BeNil()) + By("Deleted the workloaddefinitions CRD") })