Skip to content

Commit

Permalink
Merge pull request #133 from ev1lQuark/cache-selector
Browse files Browse the repository at this point in the history
feat: add support for cache selection by service
  • Loading branch information
chickenlj authored Jan 3, 2024
2 parents 6efa6b6 + f669dba commit c3ad915
Show file tree
Hide file tree
Showing 5 changed files with 365 additions and 73 deletions.
155 changes: 93 additions & 62 deletions pkg/admin/cache/registry/universal/cache.go
Original file line number Diff line number Diff line change
Expand Up @@ -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,
})
}
}
}
Expand All @@ -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,
})
}
}
}
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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
}
56 changes: 56 additions & 0 deletions pkg/admin/cache/selector/application_selector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
/*
* 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"
"k8s.io/apimachinery/pkg/labels"
)

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,
}
return selector.AsSelector()
}

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
}
124 changes: 124 additions & 0 deletions pkg/admin/cache/selector/multi_selector.go
Original file line number Diff line number Diff line change
@@ -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
}
Loading

0 comments on commit c3ad915

Please sign in to comment.