-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathwatch.go
More file actions
128 lines (107 loc) · 3.31 KB
/
Copy pathwatch.go
File metadata and controls
128 lines (107 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
package storage
import (
"fmt"
metainternalversion "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/watch"
)
// watchBroadcasterQueueLen is the default queue length for watch broadcasters.
const watchBroadcasterQueueLen = 100
// supportedWatchFieldSelectors lists the metadata fields supported for watch field selectors.
var supportedWatchFieldSelectors = map[string]bool{
"metadata.name": true,
"metadata.namespace": true,
}
// validateFieldSelector checks that all field selector requirements use supported fields.
func validateFieldSelector(sel fields.Selector) error {
if sel == nil || sel.Empty() {
return nil
}
reqs := sel.Requirements()
for _, req := range reqs {
if !supportedWatchFieldSelectors[req.Field] {
return fmt.Errorf(
"field selector %q is not supported; supported fields: metadata.name, metadata.namespace",
req.Field,
)
}
}
return nil
}
// validateUnsupportedWatchListOptions rejects watch-list options that this storage
// does not implement yet.
func validateUnsupportedWatchListOptions(opts *metainternalversion.ListOptions) error {
if opts == nil {
return nil
}
if isDefaultedLegacyWatchListOptions(opts) {
return nil
}
if opts.SendInitialEvents != nil && *opts.SendInitialEvents {
return fmt.Errorf("sendInitialEvents=true is not supported for this watch endpoint")
}
if opts.ResourceVersionMatch != "" {
return fmt.Errorf(
"resourceVersionMatch %q is not supported for this watch endpoint",
opts.ResourceVersionMatch,
)
}
return nil
}
func isDefaultedLegacyWatchListOptions(opts *metainternalversion.ListOptions) bool {
if opts == nil {
return false
}
if opts.SendInitialEvents == nil || !*opts.SendInitialEvents {
return false
}
if opts.ResourceVersionMatch != metav1.ResourceVersionMatchNotOlderThan {
return false
}
return opts.ResourceVersion == "" || opts.ResourceVersion == "0"
}
// filterForListOptions builds a watch.FilterFunc that applies namespace, label, and field selector filtering.
// Returns nil if no filtering is needed.
func filterForListOptions(requestNamespace string, opts *metainternalversion.ListOptions) (watch.FilterFunc, error) {
var labelSel labels.Selector
var fieldSel fields.Selector
if opts != nil {
if opts.LabelSelector != nil && !opts.LabelSelector.Empty() {
labelSel = opts.LabelSelector
}
if opts.FieldSelector != nil && !opts.FieldSelector.Empty() {
if err := validateFieldSelector(opts.FieldSelector); err != nil {
return nil, err
}
fieldSel = opts.FieldSelector
}
}
if requestNamespace == "" && labelSel == nil && fieldSel == nil {
return nil, nil
}
return func(in watch.Event) (watch.Event, bool) {
obj, ok := in.Object.(metav1.ObjectMetaAccessor)
if !ok {
return in, true
}
meta := obj.GetObjectMeta()
if requestNamespace != "" && meta.GetNamespace() != requestNamespace {
return in, false
}
if labelSel != nil && !labelSel.Matches(labels.Set(meta.GetLabels())) {
return in, false
}
if fieldSel != nil {
fieldSet := fields.Set{
"metadata.name": meta.GetName(),
"metadata.namespace": meta.GetNamespace(),
}
if !fieldSel.Matches(fieldSet) {
return in, false
}
}
return in, true
}, nil
}