This is an automated email from the ASF dual-hosted git repository.

liujun pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/dubbo-kubernetes.git


The following commit(s) were added to refs/heads/master by this push:
     new f669dba2 feat: cache selector
     new c3ad915b Merge pull request #133 from ev1lQuark/cache-selector
f669dba2 is described below

commit f669dba24dd6a56c9148e8955a2b7d34b3da0d48
Author: wangguan <wg1024c...@gmail.com>
AuthorDate: Tue Jan 2 21:20:07 2024 +0800

    feat: cache selector
---
 pkg/admin/cache/registry/universal/cache.go        | 155 ++++++++++++---------
 .../{selector.go => application_selector.go}       |  27 +++-
 pkg/admin/cache/selector/multi_selector.go         | 124 +++++++++++++++++
 pkg/admin/cache/selector/selector.go               |  37 +++--
 .../selector/{selector.go => service_selector.go}  |  43 ++++--
 5 files changed, 296 insertions(+), 90 deletions(-)

diff --git a/pkg/admin/cache/registry/universal/cache.go 
b/pkg/admin/cache/registry/universal/cache.go
index 28eb4241..5208fb4f 100644
--- a/pkg/admin/cache/registry/universal/cache.go
+++ b/pkg/admin/cache/registry/universal/cache.go
@@ -194,26 +194,28 @@ func (uc *UniversalCache) 
GetInstancesWithSelector(namespace string, selector se
 
        uc.providers.lock.RLock()
        for application, serviceMap := range uc.providers.data {
-               if targetApplication, ok := selector.ApplicationOption(); ok && 
targetApplication != application {
+               if !selectByApplication(selector, application) {
                        continue
-               } else {
-                       for serviceKey, instanceMap := range serviceMap {
-                               for _, dubboModel := range instanceMap {
-                                       if _, ok := 
instanceSet[dubboModel.Ip+":"+dubboModel.Port]; ok {
-                                               continue
-                                       } else {
-                                               
instanceSet[dubboModel.Ip+":"+dubboModel.Port] = struct{}{}
-                                               res = append(res, 
&cache.InstanceModel{
-                                                       Application: 
&cache.ApplicationModel{Name: application},
-                                                       Workload:    nil,
-                                                       Name:        serviceKey 
+ "#" + dubboModel.Ip + ":" + dubboModel.Port,
-                                                       Ip:          
dubboModel.Ip,
-                                                       Port:        
dubboModel.Port,
-                                                       Status:      "",
-                                                       Node:        "",
-                                                       Labels:      nil,
-                                               })
-                                       }
+               }
+               for serviceKey, instanceMap := range serviceMap {
+                       if !selectByServiceKey(selector, serviceKey) {
+                               continue
+                       }
+                       for _, dubboModel := range instanceMap {
+                               if _, ok := 
instanceSet[dubboModel.Ip+":"+dubboModel.Port]; ok {
+                                       continue
+                               } else {
+                                       
instanceSet[dubboModel.Ip+":"+dubboModel.Port] = struct{}{}
+                                       res = append(res, &cache.InstanceModel{
+                                               Application: 
&cache.ApplicationModel{Name: application},
+                                               Workload:    nil,
+                                               Name:        serviceKey + "#" + 
dubboModel.Ip + ":" + dubboModel.Port,
+                                               Ip:          dubboModel.Ip,
+                                               Port:        dubboModel.Port,
+                                               Status:      "",
+                                               Node:        "",
+                                               Labels:      nil,
+                                       })
                                }
                        }
                }
@@ -222,26 +224,28 @@ func (uc *UniversalCache) 
GetInstancesWithSelector(namespace string, selector se
 
        uc.consumers.lock.RLock()
        for application, serviceMap := range uc.consumers.data {
-               if targetApplication, ok := selector.ApplicationOption(); ok && 
targetApplication != application {
+               if !selectByApplication(selector, application) {
                        continue
-               } else {
-                       for serviceKey, instanceMap := range serviceMap {
-                               for _, dubboModel := range instanceMap {
-                                       if _, ok := 
instanceSet[dubboModel.Ip+":"+dubboModel.Port]; ok {
-                                               continue
-                                       } else {
-                                               
instanceSet[dubboModel.Ip+":"+dubboModel.Port] = struct{}{}
-                                               res = append(res, 
&cache.InstanceModel{
-                                                       Application: 
&cache.ApplicationModel{Name: application},
-                                                       Workload:    nil,
-                                                       Name:        serviceKey 
+ "#" + dubboModel.Ip + ":" + dubboModel.Port,
-                                                       Ip:          
dubboModel.Ip,
-                                                       Port:        
dubboModel.Port,
-                                                       Status:      "",
-                                                       Node:        "",
-                                                       Labels:      nil,
-                                               })
-                                       }
+               }
+               for serviceKey, instanceMap := range serviceMap {
+                       if !selectByServiceKey(selector, serviceKey) {
+                               continue
+                       }
+                       for _, dubboModel := range instanceMap {
+                               if _, ok := 
instanceSet[dubboModel.Ip+":"+dubboModel.Port]; ok {
+                                       continue
+                               } else {
+                                       
instanceSet[dubboModel.Ip+":"+dubboModel.Port] = struct{}{}
+                                       res = append(res, &cache.InstanceModel{
+                                               Application: 
&cache.ApplicationModel{Name: application},
+                                               Workload:    nil,
+                                               Name:        serviceKey + "#" + 
dubboModel.Ip + ":" + dubboModel.Port,
+                                               Ip:          dubboModel.Ip,
+                                               Port:        dubboModel.Port,
+                                               Status:      "",
+                                               Node:        "",
+                                               Labels:      nil,
+                                       })
                                }
                        }
                }
@@ -294,41 +298,46 @@ func (uc *UniversalCache) 
GetServicesWithSelector(namespace string, selector sel
 
        uc.providers.lock.RLock()
        for application, serviceMap := range uc.providers.data {
-               if targetApplication, ok := selector.ApplicationOption(); ok && 
targetApplication != application {
+               if !selectByApplication(selector, application) {
                        continue
-               } else {
-                       for serviceKey := range serviceMap {
-                               res = append(res, &cache.ServiceModel{
-                                       Application: 
&cache.ApplicationModel{Name: application},
-                                       Category:    constant.ProviderSide,
-                                       Name:        
util.GetInterface(serviceKey),
-                                       Labels:      nil,
-                                       ServiceKey:  serviceKey,
-                                       Group:       util.GetGroup(serviceKey),
-                                       Version:     
util.GetVersion(serviceKey),
-                               })
+               }
+               for serviceKey := range serviceMap {
+                       if !selectByServiceKey(selector, serviceKey) {
+                               continue
                        }
+                       res = append(res, &cache.ServiceModel{
+                               Application: &cache.ApplicationModel{Name: 
application},
+                               Category:    constant.ProviderSide,
+                               Name:        util.GetInterface(serviceKey),
+                               Labels:      nil,
+                               ServiceKey:  serviceKey,
+                               Group:       util.GetGroup(serviceKey),
+                               Version:     util.GetVersion(serviceKey),
+                       })
                }
        }
        uc.providers.lock.RUnlock()
 
        uc.consumers.lock.RLock()
        for application, serviceMap := range uc.consumers.data {
-               if targetApplication, ok := selector.ApplicationOption(); ok && 
targetApplication != application {
+               if !selectByApplication(selector, application) {
                        continue
-               } else {
-                       for serviceKey := range serviceMap {
-                               res = append(res, &cache.ServiceModel{
-                                       Application: 
&cache.ApplicationModel{Name: application},
-                                       Category:    constant.ConsumerSide,
-                                       Name:        
util.GetInterface(serviceKey),
-                                       Labels:      nil,
-                                       ServiceKey:  serviceKey,
-                                       Group:       util.GetGroup(serviceKey),
-                                       Version:     
util.GetVersion(serviceKey),
-                               })
+               }
+               for serviceKey := range serviceMap {
+                       if !selectByServiceKey(selector, serviceKey) {
+                               continue
                        }
+                       res = append(res, &cache.ServiceModel{
+                               Application: &cache.ApplicationModel{Name: 
application},
+                               Category:    constant.ConsumerSide,
+                               Name:        util.GetInterface(serviceKey),
+                               Labels:      nil,
+                               ServiceKey:  serviceKey,
+                               Group:       util.GetGroup(serviceKey),
+                               Version:     util.GetVersion(serviceKey),
+                       })
                }
+
        }
        uc.consumers.lock.RUnlock()
 
@@ -489,3 +498,25 @@ func (m *DubboModel) ToggleRegistryType(deleteType string) 
{
                m.RegistryType = constant.RegistryInstance
        }
 }
+
+// selectByServiceKey is used to determine whether the serviceKey matches the 
selector
+func selectByServiceKey(selector selector.Selector, serviceKey string) bool {
+       if serviceNameOptions, ok := selector.ServiceNameOptions(); ok && 
!serviceNameOptions.Exist(util.GetInterface(serviceKey)) {
+               return false
+       }
+       if serviceGroupOptions, ok := selector.ServiceGroupOptions(); ok && 
!serviceGroupOptions.Exist(util.GetGroup(serviceKey)) {
+               return false
+       }
+       if serviceVersionOptions, ok := selector.ServiceVersionOptions(); ok && 
!serviceVersionOptions.Exist(util.GetVersion(serviceKey)) {
+               return false
+       }
+       return true
+}
+
+// selectByApplication is used to determine whether the application matches 
the selector
+func selectByApplication(selector selector.Selector, application string) bool {
+       if applicationOptions, ok := selector.ApplicationOptions(); ok && 
!applicationOptions.Exist(application) {
+               return false
+       }
+       return true
+}
diff --git a/pkg/admin/cache/selector/selector.go 
b/pkg/admin/cache/selector/application_selector.go
similarity index 70%
copy from pkg/admin/cache/selector/selector.go
copy to pkg/admin/cache/selector/application_selector.go
index 61271525..43f580bc 100644
--- a/pkg/admin/cache/selector/selector.go
+++ b/pkg/admin/cache/selector/application_selector.go
@@ -22,15 +22,16 @@ import (
        "k8s.io/apimachinery/pkg/labels"
 )
 
-type Selector interface {
-       AsLabelsSelector() labels.Selector
-
-       ApplicationOption() (string, bool)
-}
 type ApplicationSelector struct {
        Name string
 }
 
+func NewApplicationSelector(name string) *ApplicationSelector {
+       return &ApplicationSelector{
+               Name: name,
+       }
+}
+
 func (s *ApplicationSelector) AsLabelsSelector() labels.Selector {
        selector := labels.Set{
                constant.ApplicationLabel: s.Name,
@@ -38,6 +39,18 @@ func (s *ApplicationSelector) AsLabelsSelector() 
labels.Selector {
        return selector.AsSelector()
 }
 
-func (s *ApplicationSelector) ApplicationOption() (string, bool) {
-       return s.Name, true
+func (s *ApplicationSelector) ApplicationOptions() (Options, bool) {
+       return newOptions(s.Name), true
+}
+
+func (s *ApplicationSelector) ServiceNameOptions() (Options, bool) {
+       return nil, false
+}
+
+func (s *ApplicationSelector) ServiceGroupOptions() (Options, bool) {
+       return nil, false
+}
+
+func (s *ApplicationSelector) ServiceVersionOptions() (Options, bool) {
+       return nil, false
 }
diff --git a/pkg/admin/cache/selector/multi_selector.go 
b/pkg/admin/cache/selector/multi_selector.go
new file mode 100644
index 00000000..2648461c
--- /dev/null
+++ b/pkg/admin/cache/selector/multi_selector.go
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package selector
+
+import (
+       "github.com/apache/dubbo-kubernetes/pkg/admin/constant"
+       "github.com/apache/dubbo-kubernetes/pkg/core/logger"
+       "k8s.io/apimachinery/pkg/labels"
+       "k8s.io/apimachinery/pkg/selection"
+)
+
+// MultiSelectors is an implement of Selector to combine multiple selectors, 
use NewMultiSelector to create it, and use Add to build it
+type MultiSelectors struct {
+       applicationNames []string
+       serviceNames     []string
+       serviceGroups    []string
+       serviceVersions  []string
+}
+
+func NewMultiSelector() *MultiSelectors {
+       return &MultiSelectors{
+               applicationNames: make([]string, 0),
+               serviceNames:     make([]string, 0),
+               serviceGroups:    make([]string, 0),
+               serviceVersions:  make([]string, 0),
+       }
+}
+
+func (s *MultiSelectors) Add(selector Selector) *MultiSelectors {
+       switch selector.(type) {
+       case *ApplicationSelector:
+               s.applicationNames = append(s.applicationNames, 
selector.(*ApplicationSelector).Name)
+       case *ServiceSelector:
+               s.serviceNames = append(s.serviceNames, 
selector.(*ServiceSelector).Name)
+               if selector.(*ServiceSelector).Group != "" {
+                       s.serviceGroups = append(s.serviceGroups, 
selector.(*ServiceSelector).Group)
+               }
+               if selector.(*ServiceSelector).Version != "" {
+                       s.serviceVersions = append(s.serviceVersions, 
selector.(*ServiceSelector).Version)
+               }
+       }
+       return s
+}
+
+func (s *MultiSelectors) AsLabelsSelector() labels.Selector {
+       requirements := make([]labels.Requirement, 0)
+
+       if len(s.applicationNames) > 0 {
+               req, err := labels.NewRequirement(constant.ApplicationLabel, 
selection.In, s.applicationNames)
+               if err != nil {
+                       logger.Errorf("failed to create requirement for 
application selector: %v", err)
+               }
+               requirements = append(requirements, *req)
+       }
+
+       if len(s.serviceNames) > 0 {
+               req, err := labels.NewRequirement(constant.ServiceKeyLabel, 
selection.In, s.serviceNames)
+               if err != nil {
+                       logger.Errorf("failed to create requirement for service 
selector: %v", err)
+               }
+               requirements = append(requirements, *req)
+       }
+
+       if len(s.serviceGroups) > 0 {
+               req, err := labels.NewRequirement(constant.GroupLabel, 
selection.In, s.serviceGroups)
+               if err != nil {
+                       logger.Errorf("failed to create requirement for group 
selector: %v", err)
+               }
+               requirements = append(requirements, *req)
+       }
+
+       if len(s.serviceVersions) > 0 {
+               req, err := labels.NewRequirement(constant.VersionLabel, 
selection.In, s.serviceVersions)
+               if err != nil {
+                       logger.Errorf("failed to create requirement for version 
selector: %v", err)
+               }
+               requirements = append(requirements, *req)
+       }
+
+       return labels.NewSelector().Add(requirements...)
+}
+
+func (s *MultiSelectors) ApplicationOptions() (Options, bool) {
+       if len(s.applicationNames) == 0 {
+               return nil, false
+       }
+       return newOptions(s.applicationNames...), true
+}
+
+func (s *MultiSelectors) ServiceNameOptions() (Options, bool) {
+       if len(s.serviceNames) == 0 {
+               return nil, false
+       }
+       return newOptions(s.serviceNames...), true
+}
+
+func (s *MultiSelectors) ServiceGroupOptions() (Options, bool) {
+       if len(s.serviceGroups) == 0 {
+               return nil, false
+       }
+       return newOptions(s.serviceGroups...), true
+}
+
+func (s *MultiSelectors) ServiceVersionOptions() (Options, bool) {
+       if len(s.serviceVersions) == 0 {
+               return nil, false
+       }
+       return newOptions(s.serviceVersions...), true
+}
diff --git a/pkg/admin/cache/selector/selector.go 
b/pkg/admin/cache/selector/selector.go
index 61271525..0e48bdaa 100644
--- a/pkg/admin/cache/selector/selector.go
+++ b/pkg/admin/cache/selector/selector.go
@@ -18,26 +18,41 @@
 package selector
 
 import (
-       "github.com/apache/dubbo-kubernetes/pkg/admin/constant"
        "k8s.io/apimachinery/pkg/labels"
 )
 
+// Selector is an interface for selecting resources from cache
 type Selector interface {
        AsLabelsSelector() labels.Selector
 
-       ApplicationOption() (string, bool)
+       ApplicationOptions() (Options, bool)
+       ServiceNameOptions() (Options, bool)
+       ServiceGroupOptions() (Options, bool)
+       ServiceVersionOptions() (Options, bool)
 }
-type ApplicationSelector struct {
-       Name string
+
+// Options is an interface to represent possible options of a selector at a 
certain level(e.g. application, service)
+type Options interface {
+       Len() int
+       Exist(str string) bool
 }
 
-func (s *ApplicationSelector) AsLabelsSelector() labels.Selector {
-       selector := labels.Set{
-               constant.ApplicationLabel: s.Name,
-       }
-       return selector.AsSelector()
+func newOptions(strs ...string) Options {
+       return options(strs)
+}
+
+// options is a slice of string, it implements Options interface
+type options []string
+
+func (o options) Len() int {
+       return len(o)
 }
 
-func (s *ApplicationSelector) ApplicationOption() (string, bool) {
-       return s.Name, true
+func (o options) Exist(str string) bool {
+       for _, s := range o {
+               if s == str {
+                       return true
+               }
+       }
+       return false
 }
diff --git a/pkg/admin/cache/selector/selector.go 
b/pkg/admin/cache/selector/service_selector.go
similarity index 53%
copy from pkg/admin/cache/selector/selector.go
copy to pkg/admin/cache/selector/service_selector.go
index 61271525..fd534f83 100644
--- a/pkg/admin/cache/selector/selector.go
+++ b/pkg/admin/cache/selector/service_selector.go
@@ -22,22 +22,45 @@ import (
        "k8s.io/apimachinery/pkg/labels"
 )
 
-type Selector interface {
-       AsLabelsSelector() labels.Selector
-
-       ApplicationOption() (string, bool)
+type ServiceSelector struct {
+       Name    string
+       Group   string
+       Version string
 }
-type ApplicationSelector struct {
-       Name string
+
+func NewServiceSelector(name, group, version string) *ServiceSelector {
+       return &ServiceSelector{
+               Name:    name,
+               Group:   group,
+               Version: version,
+       }
 }
 
-func (s *ApplicationSelector) AsLabelsSelector() labels.Selector {
+func (s *ServiceSelector) AsLabelsSelector() labels.Selector {
        selector := labels.Set{
-               constant.ApplicationLabel: s.Name,
+               constant.ServiceKeyLabel: s.Name,
+       }
+       if s.Group != "" {
+               selector[constant.GroupLabel] = s.Group
+       }
+       if s.Version != "" {
+               selector[constant.VersionLabel] = s.Version
        }
        return selector.AsSelector()
 }
 
-func (s *ApplicationSelector) ApplicationOption() (string, bool) {
-       return s.Name, true
+func (s *ServiceSelector) ApplicationOptions() (Options, bool) {
+       return nil, false
+}
+
+func (s *ServiceSelector) ServiceNameOptions() (Options, bool) {
+       return newOptions(s.Name), true
+}
+
+func (s *ServiceSelector) ServiceGroupOptions() (Options, bool) {
+       return newOptions(s.Group), true
+}
+
+func (s *ServiceSelector) ServiceVersionOptions() (Options, bool) {
+       return newOptions(s.Version), true
 }

Reply via email to