github.com/oam-dev/kubevela@v1.9.11/pkg/resourcekeeper/cache_test.go (about)

     1  /*
     2  Copyright 2021 The KubeVela Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  	http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package resourcekeeper
    18  
    19  import (
    20  	"context"
    21  	"testing"
    22  
    23  	"github.com/stretchr/testify/require"
    24  	appsv1 "k8s.io/api/apps/v1"
    25  	corev1 "k8s.io/api/core/v1"
    26  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    27  	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
    28  	"sigs.k8s.io/controller-runtime/pkg/client/fake"
    29  
    30  	apicommon "github.com/oam-dev/kubevela/apis/core.oam.dev/common"
    31  	"github.com/oam-dev/kubevela/apis/core.oam.dev/v1beta1"
    32  	"github.com/oam-dev/kubevela/pkg/oam"
    33  	"github.com/oam-dev/kubevela/pkg/utils/common"
    34  )
    35  
    36  func TestResourceCache(t *testing.T) {
    37  	cli := fake.NewClientBuilder().WithScheme(common.Scheme).Build()
    38  	cache := newResourceCache(cli, nil)
    39  	r := require.New(t)
    40  	createMR := func(name string) v1beta1.ManagedResource {
    41  		return v1beta1.ManagedResource{
    42  			ClusterObjectReference: apicommon.ClusterObjectReference{
    43  				ObjectReference: corev1.ObjectReference{
    44  					Name:       name,
    45  					Kind:       "Deployment",
    46  					APIVersion: appsv1.SchemeGroupVersion.String(),
    47  				},
    48  			},
    49  		}
    50  	}
    51  	r.NoError(cli.Create(context.Background(), &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "resource-1"}}))
    52  	r.NoError(cli.Create(context.Background(), &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "resource-2"}}))
    53  	r.NoError(cli.Create(context.Background(), &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "resource-3"}}))
    54  	r.NoError(cli.Create(context.Background(), &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "resource-4"}}))
    55  	r.NoError(cli.Create(context.Background(), &appsv1.Deployment{ObjectMeta: metav1.ObjectMeta{Name: "resource-6"}}))
    56  	ti := metav1.Now()
    57  	rt1 := &v1beta1.ResourceTracker{
    58  		Spec: v1beta1.ResourceTrackerSpec{
    59  			ManagedResources: []v1beta1.ManagedResource{
    60  				createMR("resource-1"),
    61  				createMR("resource-3"),
    62  			},
    63  		},
    64  	}
    65  	rt2 := &v1beta1.ResourceTracker{
    66  		ObjectMeta: metav1.ObjectMeta{DeletionTimestamp: &ti},
    67  		Spec: v1beta1.ResourceTrackerSpec{
    68  			ManagedResources: []v1beta1.ManagedResource{
    69  				createMR("resource-1"),
    70  				createMR("resource-2"),
    71  				createMR("resource-3"),
    72  				createMR("resource-4"),
    73  			},
    74  		},
    75  	}
    76  	rt3 := &v1beta1.ResourceTracker{
    77  		Spec: v1beta1.ResourceTrackerSpec{
    78  			ManagedResources: []v1beta1.ManagedResource{
    79  				createMR("resource-1"),
    80  				createMR("resource-4"),
    81  				createMR("resource-5"),
    82  			},
    83  		},
    84  	}
    85  	rts := []*v1beta1.ResourceTracker{nil, rt1, rt2, rt3}
    86  	cache.registerResourceTrackers(rts...)
    87  	mr := createMR("resource-1")
    88  	o, ok := cache.m.Get(mr.ResourceKey())
    89  	r.True(ok)
    90  	r.False(o.loaded)
    91  	for _, check := range []struct {
    92  		name           string
    93  		usedBy         []*v1beta1.ResourceTracker
    94  		latestActiveRT *v1beta1.ResourceTracker
    95  		gcExecutorRT   *v1beta1.ResourceTracker
    96  		notFound       bool
    97  	}{{
    98  		name:           "resource-1",
    99  		usedBy:         []*v1beta1.ResourceTracker{rt1, rt2, rt3},
   100  		latestActiveRT: rt3,
   101  		gcExecutorRT:   rt3,
   102  	}, {
   103  		name:           "resource-2",
   104  		usedBy:         []*v1beta1.ResourceTracker{rt2},
   105  		latestActiveRT: nil,
   106  		gcExecutorRT:   rt2,
   107  	}, {
   108  		name:           "resource-3",
   109  		usedBy:         []*v1beta1.ResourceTracker{rt1, rt2},
   110  		latestActiveRT: rt1,
   111  		gcExecutorRT:   rt1,
   112  	}, {
   113  		name:           "resource-4",
   114  		usedBy:         []*v1beta1.ResourceTracker{rt2, rt3},
   115  		latestActiveRT: rt3,
   116  		gcExecutorRT:   rt3,
   117  	}, {
   118  		name:           "resource-5",
   119  		usedBy:         []*v1beta1.ResourceTracker{rt3},
   120  		latestActiveRT: rt3,
   121  		gcExecutorRT:   rt3,
   122  		notFound:       true,
   123  	}, {
   124  		name: "resource-6",
   125  	}} {
   126  		entry := cache.get(context.Background(), createMR(check.name))
   127  		r.Equal(check.usedBy, entry.usedBy)
   128  		r.Equal(check.latestActiveRT, entry.latestActiveRT)
   129  		r.Equal(check.gcExecutorRT, entry.gcExecutorRT)
   130  		r.Equal(check.notFound, !entry.exists)
   131  		r.True(entry.loaded)
   132  	}
   133  }
   134  
   135  func TestResourceCacheExistenceCheck(t *testing.T) {
   136  	cli := fake.NewClientBuilder().WithScheme(common.Scheme).Build()
   137  	cache := newResourceCache(cli, &v1beta1.Application{ObjectMeta: metav1.ObjectMeta{
   138  		Name:      "app",
   139  		Namespace: "test",
   140  	}})
   141  	r := require.New(t)
   142  	createResource := func(appName, appNs, sharedBy string) *unstructured.Unstructured {
   143  		return &unstructured.Unstructured{Object: map[string]interface{}{
   144  			"metadata": map[string]interface{}{
   145  				"labels":          map[string]interface{}{oam.LabelAppName: appName, oam.LabelAppNamespace: appNs},
   146  				"annotations":     map[string]interface{}{oam.AnnotationAppSharedBy: sharedBy},
   147  				"resourceVersion": "-",
   148  			},
   149  		}}
   150  	}
   151  	r.True(cache.exists(createResource("app", "test", "")))
   152  	r.False(cache.exists(createResource("app-no-shared-by", "test", "")))
   153  	r.True(cache.exists(createResource("app-shared-by", "ex", "x/y,test/app,ex/app-shared-by")))
   154  }