diff --git a/cri/utils/utils.go b/cri/utils/utils.go new file mode 100644 index 0000000000..752ba6e0b5 --- /dev/null +++ b/cri/utils/utils.go @@ -0,0 +1,18 @@ +package utils + +// Move the public utility methods which are used by both v1alpha1 +// and v1alpha2 here to reduce the code duplication. + +// matchLabelSelector returns true if labels cover selector. +func matchLabelSelector(selector, labels map[string]string) bool { + for k, v := range selector { + if val, ok := labels[k]; ok { + if v != val { + return false + } + } else { + return false + } + } + return true +} diff --git a/cri/utils/utils_test.go b/cri/utils/utils_test.go new file mode 100644 index 0000000000..40294a8ae5 --- /dev/null +++ b/cri/utils/utils_test.go @@ -0,0 +1,66 @@ +package utils + +import ( + "testing" +) + +func Test_matchLabelSelector(t *testing.T) { + type args struct { + selector map[string]string + labels map[string]string + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "Normal Test", + args: args{ + selector: map[string]string{ + "a1": "b1", + "a2": "b2", + }, + labels: map[string]string{ + "a1": "b1", + "a2": "b2", + }, + }, + want: true, + }, + { + name: "Uncovered Test", + args: args{ + selector: map[string]string{ + "a1": "b1", + "a2": "b2", + }, + labels: map[string]string{ + "a2": "b2", + }, + }, + want: false, + }, + { + name: "Unmatched Test", + args: args{ + selector: map[string]string{ + "a1": "b0", + "a2": "b2", + }, + labels: map[string]string{ + "a1": "b1", + "a2": "b2", + }, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := matchLabelSelector(tt.args.selector, tt.args.labels); got != tt.want { + t.Errorf("matchLabelSelector() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/cri/v1alpha1/cri.go b/cri/v1alpha1/cri.go index 5dda38b2b6..f5cd287857 100644 --- a/cri/v1alpha1/cri.go +++ b/cri/v1alpha1/cri.go @@ -16,6 +16,7 @@ import ( apitypes "github.com/alibaba/pouch/apis/types" anno "github.com/alibaba/pouch/cri/annotations" cni "github.com/alibaba/pouch/cri/ocicni" + criutils "github.com/alibaba/pouch/cri/utils" "github.com/alibaba/pouch/cri/stream" "github.com/alibaba/pouch/daemon/config" "github.com/alibaba/pouch/daemon/mgr" @@ -822,6 +823,20 @@ func (c *CriManager) ContainerStats(ctx context.Context, r *runtime.ContainerSta func (c *CriManager) ListContainerStats(ctx context.Context, r *runtime.ListContainerStatsRequest) (*runtime.ListContainerStatsResponse, error) { opts := &mgr.ContainerListOption{All: true} filter := func(c *mgr.Container) bool { + if c.Config.Labels[containerTypeLabelKey] != containerTypeLabelContainer { + return false + } + + if r.GetFilter().GetId() != "" && c.ID != r.GetFilter().GetId() { + return false + } + if r.GetFilter().GetPodSandboxId() != "" && c.Config.Labels[sandboxIDLabelKey] != r.GetFilter().GetPodSandboxId() { + return false + } + if r.GetFilter().GetLabelSelector() != nil && + !criutils.matchLabelSelector(r.GetFilter().GetLabelSelector(), c.Config.Labels) { + return false + } return true } opts.FilterFunc = filter diff --git a/cri/v1alpha1/cri_utils.go b/cri/v1alpha1/cri_utils.go index 9d4679301c..8374743899 100644 --- a/cri/v1alpha1/cri_utils.go +++ b/cri/v1alpha1/cri_utils.go @@ -787,6 +787,20 @@ func filterCRIContainers(containers []*runtime.Container, filter *runtime.Contai return filtered } +// matchLabelSelector returns true if labels cover selector. +func matchLabelSelector(selector, labels map[string]string) bool { + for k, v := range selector { + if val, ok := labels[k]; ok { + if v != val { + return false + } + } else { + return false + } + } + return true +} + // containerNetns returns the network namespace of the given container. func containerNetns(container *mgr.Container) string { pid := container.State.Pid diff --git a/cri/v1alpha1/cri_utils_test.go b/cri/v1alpha1/cri_utils_test.go index 65e682a7ca..345291f79c 100644 --- a/cri/v1alpha1/cri_utils_test.go +++ b/cri/v1alpha1/cri_utils_test.go @@ -1199,6 +1199,67 @@ func Test_toCriContainer(t *testing.T) { } } +func Test_matchLabelSelector(t *testing.T) { + type args struct { + selector map[string]string + labels map[string]string + } + tests := []struct { + name string + args args + want bool + }{ + { + name: "Normal Test", + args: args{ + selector: map[string]string{ + "a1": "b1", + "a2": "b2", + }, + labels: map[string]string{ + "a1": "b1", + "a2": "b2", + }, + }, + want: true, + }, + { + name: "Uncovered Test", + args: args{ + selector: map[string]string{ + "a1": "b1", + "a2": "b2", + }, + labels: map[string]string{ + "a2": "b2", + }, + }, + want: false, + }, + { + name: "Unmatched Test", + args: args{ + selector: map[string]string{ + "a1": "b0", + "a2": "b2", + }, + labels: map[string]string{ + "a1": "b1", + "a2": "b2", + }, + }, + want: false, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := matchLabelSelector(tt.args.selector, tt.args.labels); got != tt.want { + t.Errorf("matchLabelSelector() = %v, want %v", got, tt.want) + } + }) + } +} + func Test_containerNetns(t *testing.T) { type args struct { container *mgr.Container diff --git a/cri/v1alpha2/cri.go b/cri/v1alpha2/cri.go index 9d67f3ce3e..0d70fad1f5 100644 --- a/cri/v1alpha2/cri.go +++ b/cri/v1alpha2/cri.go @@ -18,6 +18,7 @@ import ( anno "github.com/alibaba/pouch/cri/annotations" runtime "github.com/alibaba/pouch/cri/apis/v1alpha2" cni "github.com/alibaba/pouch/cri/ocicni" + criutils "github.com/alibaba/pouch/cri/utils" "github.com/alibaba/pouch/cri/stream" "github.com/alibaba/pouch/daemon/config" "github.com/alibaba/pouch/daemon/mgr" @@ -918,6 +919,19 @@ func (c *CriManager) ContainerStats(ctx context.Context, r *runtime.ContainerSta func (c *CriManager) ListContainerStats(ctx context.Context, r *runtime.ListContainerStatsRequest) (*runtime.ListContainerStatsResponse, error) { opts := &mgr.ContainerListOption{All: true} filter := func(c *mgr.Container) bool { + if c.Config.Labels[containerTypeLabelKey] != containerTypeLabelContainer { + return false + } + if r.GetFilter().GetId() != "" && c.ID != r.GetFilter().GetId() { + return false + } + if r.GetFilter().GetPodSandboxId() != "" && c.Config.Labels[sandboxIDLabelKey] != r.GetFilter().GetPodSandboxId() { + return false + } + if r.GetFilter().GetLabelSelector() != nil && + !criutils.matchLabelSelector(r.GetFilter().GetLabelSelector(), c.Config.Labels) { + return false + } return true } opts.FilterFunc = filter