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 <[email protected]>
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
}