feat : support mcp server auto discovery for nacos registry (#2122)

Co-authored-by: 澄潭 <zty98751@alibaba-inc.com>
This commit is contained in:
EricaLiu
2025-04-28 21:58:17 +08:00
committed by GitHub
parent a2e4f944e9
commit 5bd20aa559
15 changed files with 1710 additions and 40 deletions

View File

@@ -15,12 +15,21 @@
package memory
import (
"encoding/json"
"sort"
"strconv"
"sync"
"time"
higressconfig "github.com/alibaba/higress/pkg/config"
"github.com/alibaba/higress/registry"
"google.golang.org/protobuf/encoding/protojson"
"google.golang.org/protobuf/types/known/structpb"
"google.golang.org/protobuf/types/known/wrapperspb"
extensions "istio.io/api/extensions/v1alpha1"
"istio.io/api/networking/v1alpha3"
"istio.io/istio/pkg/config"
"istio.io/istio/pkg/config/schema/gvk"
"istio.io/pkg/log"
"github.com/alibaba/higress/pkg/common"
@@ -30,6 +39,8 @@ import (
type Cache interface {
UpdateServiceWrapper(service string, data *ServiceWrapper)
DeleteServiceWrapper(service string)
UpdateConfigCache(kind config.GroupVersionKind, key string, config *config.Config, forceDelete bool)
GetAllConfigs(kind config.GroupVersionKind) map[string]*config.Config
PurgeStaleService()
UpdateServiceEntryEndpointWrapper(service, ip, regionId, zoneId, protocol string, labels map[string]string)
GetServiceByEndpoints(requestVersions, endpoints map[string]bool, versionKey string, protocol common.Protocol) map[string][]string
@@ -44,6 +55,7 @@ func NewCache() Cache {
return &store{
mux: &sync.RWMutex{},
sew: make(map[string]*ServiceWrapper),
configs: make(map[string]map[string]*config.Config),
toBeUpdated: make([]*ServiceWrapper, 0),
toBeDeleted: make([]*ServiceWrapper, 0),
ip2services: make(map[string]map[string]bool),
@@ -54,12 +66,85 @@ func NewCache() Cache {
type store struct {
mux *sync.RWMutex
sew map[string]*ServiceWrapper
configs map[string]map[string]*config.Config
toBeUpdated []*ServiceWrapper
toBeDeleted []*ServiceWrapper
ip2services map[string]map[string]bool
deferedDelete map[string]struct{}
}
func (s *store) GetAllConfigs(kind config.GroupVersionKind) map[string]*config.Config {
s.mux.Lock()
defer s.mux.Unlock()
cfgs, exist := s.configs[kind.String()]
if !exist {
return map[string]*config.Config{}
}
if kind == gvk.WasmPlugin {
pluginConfig := &registry.WasmPluginConfig{}
var ns string
for _, cfg := range cfgs {
ns = cfg.Namespace
rule := cfg.Spec.(*registry.McpServerRule)
pluginConfig.Rules = append(pluginConfig.Rules, rule)
}
rulesBytes, err := json.Marshal(pluginConfig)
if err != nil {
log.Errorf("marshal mcp wasm plugin config error %v", err)
return map[string]*config.Config{}
}
pbs := &structpb.Struct{}
if err = protojson.Unmarshal(rulesBytes, pbs); err != nil {
log.Errorf("unmarshal mcp wasm plugin config error %v", err)
return map[string]*config.Config{}
}
wasmPlugin := &extensions.WasmPlugin{
ImagePullPolicy: extensions.PullPolicy_Always,
Phase: extensions.PluginPhase_UNSPECIFIED_PHASE,
Priority: &wrapperspb.Int32Value{Value: 30},
PluginConfig: pbs,
Url: higressconfig.McpServerWasmImageUrl,
}
return map[string]*config.Config{"wasm": &config.Config{
Meta: config.Meta{
GroupVersionKind: gvk.WasmPlugin,
Name: "istio-autogenerated-mcp-wasmplugin",
Namespace: ns,
},
Spec: wasmPlugin,
}}
}
return cfgs
}
func (s *store) UpdateConfigCache(kind config.GroupVersionKind, key string, cfg *config.Config, forceDelete bool) {
if cfg == nil && !forceDelete {
return
}
s.mux.Lock()
if forceDelete {
for _, allConfigs := range s.configs {
delete(allConfigs, key)
}
log.Infof("Delete config %s in cache", key)
} else {
if _, exist := s.configs[kind.String()]; !exist {
s.configs[kind.String()] = make(map[string]*config.Config)
}
if _, exist := s.configs[kind.String()][key]; exist {
log.Infof("Update kind %s config %s", kind.String(), key)
} else {
log.Infof("Add kind %s config %s", kind.String(), key)
}
s.configs[kind.String()][key] = cfg
}
s.mux.Unlock()
}
func (s *store) UpdateServiceEntryEndpointWrapper(service, ip, regionId, zoneId, protocol string, labels map[string]string) {
s.mux.Lock()
defer s.mux.Unlock()
@@ -226,6 +311,15 @@ func (s *store) GetAllDestinationRuleWrapper() []*ingress.WrapperDestinationRule
drwList = append(drwList, serviceEntryWrapper.DeepCopy().DestinationRuleWrapper)
}
}
configFromMcp := s.configs[gvk.DestinationRule.String()]
for _, cfg := range configFromMcp {
dr := cfg.Spec.(*v1alpha3.DestinationRule)
drwList = append(drwList, &ingress.WrapperDestinationRule{
DestinationRule: dr,
ServiceKey: ingress.ServiceKey{ServiceFQDN: dr.Host},
})
}
return drwList
}