Fix: velaql compatible with v1.2.0-beta version (#2946)

Signed-off-by: yangsoon <yangsoonlx@gmail.com>
This commit is contained in:
yangsoon
2021-12-16 21:15:07 +08:00
committed by GitHub
parent f5e04a5575
commit b57db36dd3
2 changed files with 199 additions and 7 deletions
+75 -7
View File
@@ -21,6 +21,7 @@ import (
"reflect"
"sync"
"github.com/hashicorp/go-version"
kruise "github.com/openkruise/kruise-api/apps/v1alpha1"
"github.com/pkg/errors"
appsv1 "k8s.io/api/apps/v1"
@@ -56,6 +57,8 @@ func NewAppCollector(cli client.Client, opt Option) *AppCollector {
}
}
const velaVersionNumberToUpgradeVelaQL = "v1.2.0-rc.1"
// CollectResourceFromApp collect resources created by application
func (c *AppCollector) CollectResourceFromApp() ([]Resource, error) {
ctx := context.Background()
@@ -64,7 +67,29 @@ func (c *AppCollector) CollectResourceFromApp() ([]Resource, error) {
if err := c.k8sClient.Get(ctx, appKey, app); err != nil {
return nil, err
}
var currentVersionNumber string
if annotations := app.GetAnnotations(); annotations != nil && annotations[oam.AnnotationKubeVelaVersion] != "" {
currentVersionNumber = annotations[oam.AnnotationKubeVelaVersion]
}
velaVersionToUpgradeVelaQL, _ := version.NewVersion(velaVersionNumberToUpgradeVelaQL)
currentVersion, err := version.NewVersion(currentVersionNumber)
if err != nil {
resources, err := c.FindResourceFromResourceTrackerSpec(app)
if err != nil {
return c.FindResourceFromAppliedResourcesField(app)
}
return resources, nil
}
if velaVersionToUpgradeVelaQL.GreaterThan(currentVersion) {
return c.FindResourceFromAppliedResourcesField(app)
}
return c.FindResourceFromResourceTrackerSpec(app)
}
// FindResourceFromResourceTrackerSpec find resources from ResourceTracker spec
func (c *AppCollector) FindResourceFromResourceTrackerSpec(app *v1beta1.Application) ([]Resource, error) {
ctx := context.Background()
rootRT, currentRT, historyRTs, _, err := resourcetracker.ListApplicationResourceTrackers(ctx, c.k8sClient, app)
if err != nil {
return nil, err
@@ -74,8 +99,8 @@ func (c *AppCollector) CollectResourceFromApp() ([]Resource, error) {
for _, rt := range append(historyRTs, rootRT, currentRT) {
if rt != nil {
for _, managedResource := range rt.Spec.ManagedResources {
if isResourceInTargetCluster(c.opt.Filter, managedResource) &&
isResourceInTargetComponent(c.opt.Filter, managedResource) {
if isResourceInTargetCluster(c.opt.Filter, managedResource.ClusterObjectReference) &&
isResourceInTargetComponent(c.opt.Filter, managedResource.Component) {
managedResources[managedResource.ClusterObjectReference] = true
}
}
@@ -107,6 +132,49 @@ func (c *AppCollector) CollectResourceFromApp() ([]Resource, error) {
return resources, nil
}
// FindResourceFromAppliedResourcesField find resources from AppliedResources field
func (c *AppCollector) FindResourceFromAppliedResourcesField(app *v1beta1.Application) ([]Resource, error) {
resources := make([]Resource, 0, len(app.Spec.Components))
for _, rsrcRef := range app.Status.AppliedResources {
if !isResourceInTargetCluster(c.opt.Filter, rsrcRef) {
continue
}
compName, obj, err := getObjectCreatedByComponent(c.k8sClient, rsrcRef.ObjectReference, rsrcRef.Cluster)
if err != nil {
return nil, err
}
if len(compName) != 0 && isResourceInTargetComponent(c.opt.Filter, compName) {
resources = append(resources, Resource{
Component: compName,
Revision: obj.GetLabels()[oam.LabelAppRevision],
Cluster: rsrcRef.Cluster,
Object: obj,
})
}
}
if len(resources) == 0 {
return nil, errors.Errorf("fail to find resources created by application: %v", c.opt.Name)
}
return resources, nil
}
// getObjectCreatedByComponent get k8s obj created by components
func getObjectCreatedByComponent(cli client.Client, objRef corev1.ObjectReference, cluster string) (string, *unstructured.Unstructured, error) {
ctx := multicluster.ContextWithClusterName(context.Background(), cluster)
obj := new(unstructured.Unstructured)
obj.SetGroupVersionKind(objRef.GroupVersionKind())
obj.SetNamespace(objRef.Namespace)
obj.SetName(objRef.Name)
if err := cli.Get(ctx, client.ObjectKeyFromObject(obj), obj); err != nil {
if kerrors.IsNotFound(err) {
return "", nil, nil
}
return "", nil, err
}
componentName := obj.GetLabels()[oam.LabelAppComponent]
return componentName, obj, nil
}
var standardWorkloads = []schema.GroupVersionKind{
appsv1.SchemeGroupVersion.WithKind(reflect.TypeOf(appsv1.Deployment{}).Name()),
appsv1.SchemeGroupVersion.WithKind(reflect.TypeOf(appsv1.ReplicaSet{}).Name()),
@@ -316,22 +384,22 @@ func getEventFieldSelector(obj *unstructured.Unstructured) fields.Selector {
return field.AsSelector()
}
func isResourceInTargetCluster(opt FilterOption, managedResource v1beta1.ManagedResource) bool {
func isResourceInTargetCluster(opt FilterOption, resource common.ClusterObjectReference) bool {
if opt.Cluster == "" && opt.ClusterNamespace == "" {
return true
}
if opt.Cluster == managedResource.Cluster && opt.ClusterNamespace == managedResource.ObjectReference.Namespace {
if opt.Cluster == resource.Cluster && opt.ClusterNamespace == resource.ObjectReference.Namespace {
return true
}
return false
}
func isResourceInTargetComponent(opt FilterOption, managedResource v1beta1.ManagedResource) bool {
if len(opt.Components) == 0 {
func isResourceInTargetComponent(opt FilterOption, componentName string) bool {
if len(opt.Components) == 0 && len(componentName) != 0 {
return true
}
for _, component := range opt.Components {
if component == managedResource.Component {
if component == componentName {
return true
}
}
+124
View File
@@ -19,6 +19,7 @@ package query
import (
"encoding/json"
"fmt"
"time"
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
@@ -26,8 +27,11 @@ import (
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/yaml"
"github.com/oam-dev/kubevela/apis/core.oam.dev/common"
"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
"github.com/oam-dev/kubevela/pkg/cue/model/value"
"github.com/oam-dev/kubevela/pkg/oam"
"github.com/oam-dev/kubevela/pkg/oam/util"
@@ -63,6 +67,126 @@ var _ = Describe("Test Query Provider", func() {
})
Context("Test ListResourcesInApp", func() {
It("Test list latest resources created by application", func() {
namespace := "test"
ns := corev1.Namespace{ObjectMeta: metav1.ObjectMeta{Name: namespace}}
Expect(k8sClient.Create(ctx, &ns)).Should(BeNil())
app := v1beta1.Application{
ObjectMeta: metav1.ObjectMeta{
Name: "test",
Namespace: "test",
Annotations: map[string]string{
"oam.dev/kubevela-version": "v1.2.0-beta.2",
},
},
Spec: v1beta1.ApplicationSpec{
Components: []common.ApplicationComponent{{
Name: "web",
Type: "webservice",
Properties: util.Object2RawExtension(map[string]string{
"image": "busybox",
}),
Traits: []common.ApplicationTrait{{
Type: "expose",
Properties: util.Object2RawExtension(map[string]interface{}{
"ports": []int{8000},
}),
}},
}},
},
}
Expect(k8sClient.Create(ctx, &app)).Should(BeNil())
oldApp := new(v1beta1.Application)
Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(&app), oldApp)).Should(BeNil())
oldApp.Status.LatestRevision = &common.Revision{
Revision: 1,
}
oldApp.Status.AppliedResources = []common.ClusterObjectReference{{
Cluster: "",
Creator: "workflow",
ObjectReference: corev1.ObjectReference{
APIVersion: "v1",
Kind: "Service",
Namespace: namespace,
Name: "web",
},
}, {
Cluster: "",
Creator: "workflow",
ObjectReference: corev1.ObjectReference{
APIVersion: "apps/v1",
Kind: "Deployment",
Namespace: namespace,
Name: "web",
},
}}
Eventually(func() error {
err := k8sClient.Status().Update(ctx, oldApp)
if err != nil {
return err
}
return nil
}, 300*time.Microsecond, 3*time.Second).Should(BeNil())
appDeploy := baseDeploy.DeepCopy()
appDeploy.SetName("web")
appDeploy.SetNamespace(namespace)
appDeploy.SetLabels(map[string]string{
oam.LabelAppComponent: "web",
oam.LabelAppRevision: "test-v1",
})
Expect(k8sClient.Create(ctx, appDeploy)).Should(BeNil())
appService := baseService.DeepCopy()
appService.SetName("web")
appService.SetNamespace(namespace)
appService.SetLabels(map[string]string{
oam.LabelAppComponent: "web",
oam.LabelAppRevision: "test-v1",
})
Expect(k8sClient.Create(ctx, appService)).Should(BeNil())
prd := provider{cli: k8sClient}
opt := `app: {
name: "test"
namespace: "test"
filter: {
cluster: "",
clusterNamespace: "test",
components: ["web"]
}
}`
v, err := value.NewValue(opt, nil, "")
Expect(err).Should(BeNil())
Expect(prd.ListResourcesInApp(nil, v, nil)).Should(BeNil())
appResList := new(AppResourcesList)
Expect(v.UnmarshalTo(appResList)).Should(BeNil())
Expect(len(appResList.List)).Should(Equal(2))
Expect(appResList.List[0].Object.GroupVersionKind()).Should(Equal(oldApp.Status.AppliedResources[0].GroupVersionKind()))
Expect(appResList.List[1].Object.GroupVersionKind()).Should(Equal(oldApp.Status.AppliedResources[1].GroupVersionKind()))
updateApp := new(v1beta1.Application)
Expect(k8sClient.Get(ctx, client.ObjectKeyFromObject(&app), updateApp)).Should(BeNil())
updateApp.ObjectMeta.Annotations = map[string]string{
"oam.dev/kubevela-version": "master",
}
Expect(k8sClient.Update(ctx, updateApp)).Should(BeNil())
newValue, err := value.NewValue(opt, nil, "")
Expect(err).Should(BeNil())
Expect(prd.ListResourcesInApp(nil, newValue, nil)).Should(BeNil())
newAppResList := new(AppResourcesList)
Expect(v.UnmarshalTo(newAppResList)).Should(BeNil())
Expect(len(newAppResList.List)).Should(Equal(2))
Expect(newAppResList.List[0].Object.GroupVersionKind()).Should(Equal(updateApp.Status.AppliedResources[0].GroupVersionKind()))
Expect(newAppResList.List[1].Object.GroupVersionKind()).Should(Equal(updateApp.Status.AppliedResources[1].GroupVersionKind()))
})
It("Test list resource with incomplete parameter", func() {
optWithoutApp := ""
prd := provider{cli: k8sClient}