fix metadata missing in AppRevision spec data (#1257)

* fix metadata missing in AppRevision spec data

* fix test
This commit is contained in:
Hongchao Deng
2021-03-22 11:29:25 +08:00
committed by GitHub
parent 0b72c7ce34
commit 75c123df2f
7 changed files with 90 additions and 1717 deletions
@@ -43,6 +43,7 @@ import (
"sigs.k8s.io/yaml"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1alpha2"
"github.com/oam-dev/kubevela/pkg/controller/core.oam.dev/v1alpha2/applicationcontext"
"github.com/oam-dev/kubevela/pkg/controller/utils"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/util"
@@ -360,7 +361,10 @@ var _ = Describe("Test Application Controller", func() {
}, appRevision)).Should(BeNil())
gotTrait := unstructured.Unstructured{}
Expect(json.Unmarshal(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Traits[0].Trait.Raw,
ac, err := applicationcontext.ConvertRawExtention2AppConfig(appRevision.Spec.ApplicationConfiguration)
Expect(err).Should(BeNil())
Expect(json.Unmarshal(ac.Spec.Components[0].Traits[0].Trait.Raw,
&gotTrait)).Should(BeNil())
Expect(gotTrait).Should(BeEquivalentTo(expectScalerTrait("myweb3", app.Name)))
@@ -429,12 +433,16 @@ var _ = Describe("Test Application Controller", func() {
Namespace: app.Namespace,
Name: curApp.Status.LatestRevision.Name,
}, appRevision)).Should(BeNil())
Expect(appContext.Spec.ApplicationRevisionName).Should(Equal(appRevision.Name))
Expect(len(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Traits)).Should(BeEquivalentTo(2))
Expect(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].ComponentName).Should(BeEmpty())
Expect(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].RevisionName).ShouldNot(BeEmpty())
ac, err := applicationcontext.ConvertRawExtention2AppConfig(appRevision.Spec.ApplicationConfiguration)
Expect(err).Should(BeNil())
Expect(len(ac.Spec.Components[0].Traits)).Should(BeEquivalentTo(2))
Expect(ac.Spec.Components[0].ComponentName).Should(BeEmpty())
Expect(ac.Spec.Components[0].RevisionName).ShouldNot(BeEmpty())
// component create handler may create a v2 when it can't find v1
Expect(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].RevisionName).Should(
Expect(ac.Spec.Components[0].RevisionName).Should(
SatisfyAny(BeEquivalentTo(utils.ConstructRevisionName(compName, 1)),
BeEquivalentTo(utils.ConstructRevisionName(compName, 2))))
@@ -460,13 +468,15 @@ var _ = Describe("Test Application Controller", func() {
},
},
}}
Expect(json.Unmarshal(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil())
ac, err = applicationcontext.ConvertRawExtention2AppConfig(appRevision.Spec.ApplicationConfiguration)
Expect(err).Should(BeNil())
Expect(json.Unmarshal(ac.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil())
fmt.Println(cmp.Diff(expectServiceTrait, gotTrait))
Expect(assert.ObjectsAreEqual(expectServiceTrait, gotTrait)).Should(BeTrue())
By("Check the second trait should be scaler")
gotTrait = unstructured.Unstructured{}
Expect(json.Unmarshal(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Traits[1].Trait.Raw, &gotTrait)).Should(BeNil())
Expect(json.Unmarshal(ac.Spec.Components[0].Traits[1].Trait.Raw, &gotTrait)).Should(BeNil())
Expect(gotTrait).Should(BeEquivalentTo(expectScalerTrait("myweb-composed-3", app.Name)))
By("Check component created as expected")
@@ -527,10 +537,12 @@ var _ = Describe("Test Application Controller", func() {
Expect(appContext.Spec.ApplicationRevisionName).Should(Equal(appRevision.Name))
gotTrait := unstructured.Unstructured{}
Expect(json.Unmarshal(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil())
ac, err := applicationcontext.ConvertRawExtention2AppConfig(appRevision.Spec.ApplicationConfiguration)
Expect(err).Should(BeNil())
Expect(json.Unmarshal(ac.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil())
Expect(gotTrait).Should(BeEquivalentTo(expectScalerTrait("myweb4", app.Name)))
Expect(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Scopes[0].ScopeReference).Should(BeEquivalentTo(v1alpha1.TypedReference{
Expect(ac.Spec.Components[0].Scopes[0].ScopeReference).Should(BeEquivalentTo(v1alpha1.TypedReference{
APIVersion: "core.oam.dev/v1alpha2",
Kind: "HealthScope",
Name: "appWithTraitAndScope-default-health",
@@ -595,15 +607,17 @@ var _ = Describe("Test Application Controller", func() {
Expect(appContext.Spec.ApplicationRevisionName).Should(Equal(appRevision.Name))
gotTrait := unstructured.Unstructured{}
Expect(json.Unmarshal(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil())
ac, err := applicationcontext.ConvertRawExtention2AppConfig(appRevision.Spec.ApplicationConfiguration)
Expect(err).Should(BeNil())
Expect(json.Unmarshal(ac.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil())
Expect(gotTrait).Should(BeEquivalentTo(expectScalerTrait("myweb5", app.Name)))
Expect(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Scopes[0].ScopeReference).Should(BeEquivalentTo(v1alpha1.TypedReference{
Expect(ac.Spec.Components[0].Scopes[0].ScopeReference).Should(BeEquivalentTo(v1alpha1.TypedReference{
APIVersion: "core.oam.dev/v1alpha2",
Kind: "HealthScope",
Name: "app-with-two-comp-default-health",
}))
Expect(appRevision.Spec.ApplicationConfiguration.Spec.Components[1].Scopes[0].ScopeReference).Should(BeEquivalentTo(v1alpha1.TypedReference{
Expect(ac.Spec.Components[1].Scopes[0].ScopeReference).Should(BeEquivalentTo(v1alpha1.TypedReference{
APIVersion: "core.oam.dev/v1alpha2",
Kind: "HealthScope",
Name: "app-with-two-comp-default-health",
@@ -667,15 +681,15 @@ var _ = Describe("Test Application Controller", func() {
}, appRevision)).Should(BeNil())
Expect(appContext.Spec.ApplicationRevisionName).Should(Equal(appRevision.Name))
Expect(json.Unmarshal(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil())
Expect(json.Unmarshal(ac.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil())
Expect(gotTrait).Should(BeEquivalentTo(expectScalerTrait("myweb5", app.Name)))
Expect(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Scopes[0].ScopeReference).Should(BeEquivalentTo(v1alpha1.TypedReference{
Expect(ac.Spec.Components[0].Scopes[0].ScopeReference).Should(BeEquivalentTo(v1alpha1.TypedReference{
APIVersion: "core.oam.dev/v1alpha2",
Kind: "HealthScope",
Name: "app-with-two-comp-default-health",
}))
Expect(appRevision.Spec.ApplicationConfiguration.Spec.Components[1].Scopes[0].ScopeReference).Should(BeEquivalentTo(v1alpha1.TypedReference{
Expect(ac.Spec.Components[1].Scopes[0].ScopeReference).Should(BeEquivalentTo(v1alpha1.TypedReference{
APIVersion: "core.oam.dev/v1alpha2",
Kind: "HealthScope",
Name: "app-with-two-comp-default-health",
@@ -752,7 +766,10 @@ var _ = Describe("Test Application Controller", func() {
}, appRevision)).Should(BeNil())
Expect(appContext.Spec.ApplicationRevisionName).Should(Equal(appRevision.Name))
gotTrait := unstructured.Unstructured{}
Expect(json.Unmarshal(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil())
ac, err := applicationcontext.ConvertRawExtention2AppConfig(appRevision.Spec.ApplicationConfiguration)
Expect(err).Should(BeNil())
Expect(json.Unmarshal(ac.Spec.Components[0].Traits[0].Trait.Raw, &gotTrait)).Should(BeNil())
Expect(gotTrait).Should(BeEquivalentTo(expTrait))
Expect(k8sClient.Delete(ctx, app)).Should(BeNil())
@@ -916,11 +933,13 @@ var _ = Describe("Test Application Controller", func() {
Expect(component.Status.LatestRevision).ShouldNot(BeNil())
Expect(component.Status.LatestRevision.Revision).Should(BeEquivalentTo(1))
// check that the new appconfig has the correct annotation and labels
Expect(appRevision.Spec.ApplicationConfiguration.GetAnnotations()[oam.AnnotationAppRollout]).Should(Equal(strconv.FormatBool(true)))
Expect(appRevision.Spec.ApplicationConfiguration.GetAnnotations()["keep"]).Should(Equal("true"))
Expect(appRevision.Spec.ApplicationConfiguration.GetLabels()[oam.LabelAppRevisionHash]).ShouldNot(BeEmpty())
Expect(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].ComponentName).Should(BeEmpty())
Expect(appRevision.Spec.ApplicationConfiguration.Spec.Components[0].RevisionName).Should(Equal(component.Status.LatestRevision.Name))
ac, err := applicationcontext.ConvertRawExtention2AppConfig(appRevision.Spec.ApplicationConfiguration)
Expect(err).Should(BeNil())
Expect(ac.GetAnnotations()[oam.AnnotationAppRollout]).Should(Equal(strconv.FormatBool(true)))
Expect(ac.GetAnnotations()["keep"]).Should(Equal("true"))
Expect(ac.GetLabels()[oam.LabelAppRevisionHash]).ShouldNot(BeEmpty())
Expect(ac.Spec.Components[0].ComponentName).Should(BeEmpty())
Expect(ac.Spec.Components[0].RevisionName).Should(Equal(component.Status.LatestRevision.Name))
By("Reconcile again to make sure we are not creating more appConfigs")
reconcileRetry(reconciler, reconcile.Request{NamespacedName: appKey})
@@ -26,6 +26,7 @@ import (
"github.com/oam-dev/kubevela/apis/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/oam/util"
)
// AppRevisionHash is used to compute the hash value of the AppRevision
@@ -45,8 +46,8 @@ func (h *appHandler) GenerateRevision(ctx context.Context, ac *v1alpha2.Applicat
appRev := &v1alpha2.ApplicationRevision{
Spec: v1alpha2.ApplicationRevisionSpec{
Application: *copiedApp,
Components: comps,
ApplicationConfiguration: *ac,
Components: convertComponentList2Map(comps),
ApplicationConfiguration: util.Object2RawExtension(ac),
ComponentDefinitions: make(map[string]v1alpha2.ComponentDefinition),
WorkloadDefinitions: make(map[string]v1alpha2.WorkloadDefinition),
TraitDefinitions: make(map[string]v1alpha2.TraitDefinition),
@@ -118,6 +119,15 @@ func (h *appHandler) GenerateRevision(ctx context.Context, ac *v1alpha2.Applicat
return true, appRev, nil
}
func convertComponentList2Map(comps []*v1alpha2.Component) map[string]v1alpha2.Component {
objs := map[string]v1alpha2.Component{}
for _, comp := range comps {
obj := comp.DeepCopy()
objs[comp.Name] = *obj
}
return objs
}
// DeepEqualRevision will check the Application and Definition to see if the Application is the same revision
// AC and component are generated by the application and definitions
func DeepEqualRevision(old, new *v1alpha2.ApplicationRevision) bool {
@@ -2,6 +2,7 @@ package applicationcontext
import (
"context"
"encoding/json"
"fmt"
"strings"
"time"
@@ -11,6 +12,7 @@ import (
"github.com/pkg/errors"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -74,7 +76,11 @@ func (r *Reconciler) Reconcile(request reconcile.Request) (reconcile.Result, err
}
// copy the status
appConfig := appRevision.Spec.ApplicationConfiguration.DeepCopy()
acRaw := appRevision.Spec.ApplicationConfiguration
appConfig, err := ConvertRawExtention2AppConfig(acRaw)
if err != nil {
return reconcile.Result{}, err
}
appConfig.Status = appContext.Status
// the name of the appConfig has to be the same as the appContext
appConfig.ObjectMeta = metav1.ObjectMeta{Namespace: appContext.Namespace, Name: appContext.Name, UID: appContext.UID}
@@ -91,6 +97,19 @@ func (r *Reconciler) Reconcile(request reconcile.Request) (reconcile.Result, err
return reconResult, err
}
// ConvertRawExtention2AppConfig converts runtime.RawExtention to ApplicationConfiguration
func ConvertRawExtention2AppConfig(raw runtime.RawExtension) (*v1alpha2.ApplicationConfiguration, error) {
ac := &v1alpha2.ApplicationConfiguration{}
b, err := raw.MarshalJSON()
if err != nil {
return nil, err
}
if err := json.Unmarshal(b, ac); err != nil {
return nil, err
}
return ac, nil
}
// SetupWithManager setup the controller with manager
func (r *Reconciler) SetupWithManager(mgr ctrl.Manager) error {
r.record = event.NewAPIRecorder(mgr.GetEventRecorderFor("AppRollout")).