Skip to content

Commit b4240a1

Browse files
committed
feat(filter): 添加了ExcludedLabelSelector和ExcludedOrLabelSelectors字段,用于在备份过程中排除特定标签的对象。
1 parent 702dd04 commit b4240a1

File tree

4 files changed

+140
-29
lines changed

4 files changed

+140
-29
lines changed

api/v1/schedule_types.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,20 @@ type BackupSpec struct {
5252
// +nullable
5353
OrLabelSelectors []*metav1.LabelSelector `json:"orLabelSelectors,omitempty"`
5454

55+
// ExcludedLabelSelector is a metav1.labelSelector to filter out resources.
56+
// If provided, any resources matching this label selector will be excluded from the backup.
57+
// +optional
58+
// +nullable
59+
ExcludedLabelSelector *metav1.LabelSelector `json:"excludedLabelSelector,omitempty"`
60+
61+
// ExcludedOrLabelSelectors is a list of metav1.labelSelector to filter out resources.
62+
// If multiple provided, they will be joined by the OR operator.
63+
// ExcludedLabelSelector as well as ExcludedOrLabelSelectors cannot co-exist in backup request,
64+
// only one of them can be used.
65+
// +optional
66+
// +nullable
67+
ExcludedOrLabelSelectors []*metav1.LabelSelector `json:"excludedOrLabelSelectors,omitempty"`
68+
5569
// TTL is a time.Duration-parseable string describing how long
5670
// Snapshot lifecycle
5771
// +optional

internal/controller/schedule_controller.go

Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,6 @@ func (r *ScheduleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
8888
return ctrl.Result{}, errors.Wrapf(err, "error getting schedule %s", req.String())
8989
}
9090

91-
// 更新状态
9291
if err := r.updateScheduleStatus(schedule); err != nil {
9392
return ctrl.Result{}, err
9493
}
@@ -99,8 +98,8 @@ func (r *ScheduleReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c
9998
}
10099

101100
var wg sync.WaitGroup
102-
var mu sync.Mutex // 用于保护错误变量
103-
var e []error // 存储错误信息
101+
var mu sync.Mutex
102+
var e []error
104103

105104
wg.Add(2)
106105
go func() {
@@ -205,7 +204,7 @@ func (r *ScheduleReconciler) getNextRunTime(schedule string, now time.Time) time
205204
r.Log.Error(err, "error parsing schedule")
206205
return time.Time{}
207206
}
208-
// 计算下次运行时间
207+
// 计算下一次运行时间
209208
nextRunTime := now.Add(interval)
210209
return nextRunTime
211210
}
@@ -261,25 +260,28 @@ func (r *ScheduleReconciler) getResourcesToBackup(schedule *hitoseacomv1.Schedul
261260
}
262261

263262
filteredResources := (&filter.VirtualMachineFilter{
264-
IncludedNamespaces: schedule.Spec.Template.IncludedNamespaces,
265-
ExcludedNamespaces: schedule.Spec.Template.ExcludedNamespaces,
266-
LabelSelector: schedule.Spec.Template.LabelSelector,
267-
OrLabelSelectors: schedule.Spec.Template.OrLabelSelectors,
263+
IncludedNamespaces: schedule.Spec.Template.IncludedNamespaces,
264+
ExcludedNamespaces: schedule.Spec.Template.ExcludedNamespaces,
265+
LabelSelector: schedule.Spec.Template.LabelSelector,
266+
OrLabelSelectors: schedule.Spec.Template.OrLabelSelectors,
267+
ExcludedLabelSelector: schedule.Spec.Template.ExcludedLabelSelector,
268+
ExcludedOrLabelSelectors: schedule.Spec.Template.ExcludedOrLabelSelectors,
268269
}).Filter(resources)
269270

270271
return filteredResources, nil
271272
}
272273

273274
func (r *ScheduleReconciler) deleteExpiredSnapshots(ctx context.Context, schedule *hitoseacomv1.Schedule) error {
274275
nextRunTime := schedule.Status.NextDelete.Time
276+
// 检查下次删除的时间是否已到
275277
if r.ifDue(nextRunTime, r.Clock.Now()) {
276278
vmsList := &hitoseacomv1.VirtualMachineSnapshotList{}
277279
if err := r.Client.List(context.TODO(), vmsList); err != nil {
278280
r.Log.Error(err, "get VirtualMachineSnapshotList")
279281
return err
280282
}
281283

282-
// 先过滤掉特定标签的快照
284+
// 只获取Schedule创建的虚拟机快照资源
283285
var filteredVMSSList []hitoseacomv1.VirtualMachineSnapshot
284286
for _, vms := range vmsList.Items {
285287
if _, ok := vms.ObjectMeta.Labels[ScheduleSnapshotLabelKey]; ok && vms.Status.Phase != hitoseacomv1.InProgress {
@@ -292,7 +294,7 @@ func (r *ScheduleReconciler) deleteExpiredSnapshots(ctx context.Context, schedul
292294
creationTime := vmss.ObjectMeta.CreationTimestamp.Time
293295
expirationTime := creationTime.Add(schedule.Spec.Template.TTL.Duration)
294296

295-
// ttl到期
297+
// 判断是否超过了TTL过期时间
296298
if r.Clock.Now().After(expirationTime) {
297299
if err := r.Snap.DeleteSnapshot(ctx, vmss.Name, vmss.Namespace); err != nil {
298300
r.Log.Error(err, "DeleteSnapshot")

pkg/util/filter/filter.go

Lines changed: 48 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@ type ResourceFilter interface {
1212
}
1313

1414
type VirtualMachineFilter struct {
15-
IncludedNamespaces []string `json:"includedNamespaces,omitempty"`
16-
ExcludedNamespaces []string `json:"excludedNamespaces,omitempty"`
17-
LabelSelector *metav1.LabelSelector `json:"labelSelector,omitempty"`
18-
OrLabelSelectors []*metav1.LabelSelector `json:"orLabelSelectors,omitempty"`
15+
IncludedNamespaces []string `json:"includedNamespaces,omitempty"`
16+
ExcludedNamespaces []string `json:"excludedNamespaces,omitempty"`
17+
LabelSelector *metav1.LabelSelector `json:"labelSelector,omitempty"`
18+
OrLabelSelectors []*metav1.LabelSelector `json:"orLabelSelectors,omitempty"`
19+
ExcludedLabelSelector *metav1.LabelSelector `json:"excludedLabelSelector,omitempty"`
20+
ExcludedOrLabelSelectors []*metav1.LabelSelector `json:"excludedOrLabelSelectors,omitempty"`
1921
}
2022

2123
func (f *VirtualMachineFilter) Filter(resources []*unstructured.Unstructured) []*unstructured.Unstructured {
@@ -43,6 +45,16 @@ func (f *VirtualMachineFilter) Filter(resources []*unstructured.Unstructured) []
4345
continue
4446
}
4547

48+
// Check if the resource matches the excluded label selector
49+
if f.ExcludedLabelSelector != nil && f.matchesExcludedLabelSelector(resource) {
50+
continue
51+
}
52+
53+
// Check if the resource matches any of the OR excluded label selectors
54+
if f.matchesOrExcludedLabelSelectors(resource) {
55+
continue
56+
}
57+
4658
// Add the resource to the filtered list
4759
filteredResources = append(filteredResources, resource)
4860
}
@@ -105,3 +117,35 @@ func (f *VirtualMachineFilter) matchesOrLabelSelectors(resource *unstructured.Un
105117

106118
return false
107119
}
120+
121+
func (f *VirtualMachineFilter) matchesExcludedLabelSelector(resource *unstructured.Unstructured) bool {
122+
if f.ExcludedLabelSelector == nil {
123+
return false
124+
}
125+
126+
selector, err := metav1.LabelSelectorAsSelector(f.ExcludedLabelSelector)
127+
if err != nil {
128+
return false
129+
}
130+
131+
return selector.Matches(labels.Set(resource.GetLabels()))
132+
}
133+
134+
func (f *VirtualMachineFilter) matchesOrExcludedLabelSelectors(resource *unstructured.Unstructured) bool {
135+
if f.ExcludedOrLabelSelectors == nil {
136+
return false
137+
}
138+
139+
for _, selector := range f.ExcludedOrLabelSelectors {
140+
selector, err := metav1.LabelSelectorAsSelector(selector)
141+
if err != nil {
142+
continue
143+
}
144+
145+
if selector.Matches(labels.Set(resource.GetLabels())) {
146+
return true
147+
}
148+
}
149+
150+
return false
151+
}

pkg/util/filter/filter_test.go

Lines changed: 66 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -36,31 +36,51 @@ func createVirtualMachineList() *kubevirtv1.VirtualMachineList {
3636
},
3737
},
3838
}
39+
vm4 := kubevirtv1.VirtualMachine{
40+
ObjectMeta: metav1.ObjectMeta{
41+
Name: "vm4",
42+
Namespace: "namespace3",
43+
Labels: map[string]string{
44+
"app": "app2",
45+
},
46+
},
47+
}
48+
vm5 := kubevirtv1.VirtualMachine{
49+
ObjectMeta: metav1.ObjectMeta{
50+
Name: "vm5",
51+
Namespace: "namespace3",
52+
Labels: map[string]string{
53+
"app": "app3",
54+
},
55+
},
56+
}
3957
vmList := &kubevirtv1.VirtualMachineList{}
40-
vmList.Items = append(vmList.Items, vm1, vm2, vm3)
58+
vmList.Items = append(vmList.Items, vm1, vm2, vm3, vm4, vm5)
4159
return vmList
4260
}
4361

4462
func TestVirtualMachineFilter_Filter(t *testing.T) {
4563
vmList := createVirtualMachineList()
4664

4765
testCases := []struct {
48-
name string
49-
includedNamespaces []string
50-
excludedNamespaces []string
51-
labelSelector *metav1.LabelSelector
52-
orLabelSelectors []*metav1.LabelSelector
53-
expectedLength int
66+
name string
67+
includedNamespaces []string
68+
excludedNamespaces []string
69+
labelSelector *metav1.LabelSelector
70+
orLabelSelectors []*metav1.LabelSelector
71+
excludedLabelSelector *metav1.LabelSelector
72+
excludedOrLabelSelectors []*metav1.LabelSelector
73+
expectedLength int
5474
}{
5575
{
5676
name: "IncludedNamespaces",
57-
includedNamespaces: []string{"namespace1"},
58-
expectedLength: 1,
77+
includedNamespaces: []string{"namespace1", "namespace3"},
78+
expectedLength: 3,
5979
},
6080
{
6181
name: "ExcludedNamespaces",
6282
excludedNamespaces: []string{"namespace2"},
63-
expectedLength: 1,
83+
expectedLength: 3,
6484
},
6585
{
6686
name: "LabelSelector",
@@ -79,16 +99,47 @@ func TestVirtualMachineFilter_Filter(t *testing.T) {
7999
MatchLabels: map[string]string{"app": "app3"},
80100
},
81101
},
82-
expectedLength: 2,
102+
expectedLength: 4,
103+
},
104+
{
105+
name: "ExcludedLabelSelector",
106+
excludedLabelSelector: &metav1.LabelSelector{
107+
MatchLabels: map[string]string{"app": "app2"},
108+
},
109+
expectedLength: 3,
110+
},
111+
{
112+
name: "ExcludedOrLabelSelectors",
113+
excludedOrLabelSelectors: []*metav1.LabelSelector{
114+
{
115+
MatchLabels: map[string]string{"app": "app2"},
116+
},
117+
{
118+
MatchLabels: map[string]string{"app": "app3"},
119+
},
120+
},
121+
expectedLength: 1, // Excludes resources with "app=app2" or "app=app3"
122+
},
123+
{
124+
name: "IncludedAndExcludedLabelSelector",
125+
includedNamespaces: []string{"namespace2"},
126+
excludedLabelSelector: &metav1.LabelSelector{
127+
MatchLabels: map[string]string{"app": "app2"},
128+
},
129+
expectedLength: 1, // Namespace included but label excluded
83130
},
131+
// Add more test cases here to cover other combinations
84132
}
85133

134+
// Run tests for each test case
86135
for _, tc := range testCases {
87136
filter := &VirtualMachineFilter{
88-
IncludedNamespaces: tc.includedNamespaces,
89-
ExcludedNamespaces: tc.excludedNamespaces,
90-
LabelSelector: tc.labelSelector,
91-
OrLabelSelectors: tc.orLabelSelectors,
137+
IncludedNamespaces: tc.includedNamespaces,
138+
ExcludedNamespaces: tc.excludedNamespaces,
139+
LabelSelector: tc.labelSelector,
140+
OrLabelSelectors: tc.orLabelSelectors,
141+
ExcludedLabelSelector: tc.excludedLabelSelector,
142+
ExcludedOrLabelSelectors: tc.excludedOrLabelSelectors,
92143
}
93144

94145
var resources []*unstructured.Unstructured

0 commit comments

Comments
 (0)