pkg/admin/model/application.go (331 lines of code) (raw):

/* * 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 model import ( "encoding/json" "fmt" "regexp" "strconv" ) import ( "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1" "github.com/apache/dubbo-kubernetes/pkg/admin/constants" "github.com/apache/dubbo-kubernetes/pkg/config/core" "github.com/apache/dubbo-kubernetes/pkg/core/managers/apis/dataplane" "github.com/apache/dubbo-kubernetes/pkg/core/resources/apis/mesh" core_runtime "github.com/apache/dubbo-kubernetes/pkg/core/runtime" ) // Todo Application Detail type ApplicationDetailReq struct { AppName string `form:"appName"` } type ApplicationDetailResp struct { AppName string `json:"appName"` AppTypes []string `json:"appTypes"` DeployClusters []string `json:"deployClusters"` DubboPorts []string `json:"dubboPorts"` DubboVersions []string `json:"dubboVersions"` Images []string `json:"images"` RegisterClusters []string `json:"registerClusters"` RegisterModes []string `json:"registerModes"` RPCProtocols []string `json:"rpcProtocols"` SerialProtocols []string `json:"serialProtocols"` Workloads []string `json:"workloads"` } func (r *ApplicationDetailResp) FromApplicationDetail(ad *ApplicationDetail) *ApplicationDetailResp { r.AppTypes = ad.AppTypes.Values() r.DeployClusters = ad.DeployClusters.Values() r.DubboPorts = ad.DubboPorts.Values() r.DubboVersions = ad.DubboVersions.Values() r.Images = ad.Images.Values() r.RegisterClusters = ad.RegisterClusters.Values() r.RegisterModes = ad.RegisterModes.Values() r.RPCProtocols = ad.RPCProtocols.Values() r.SerialProtocols = ad.SerialProtocols.Values() r.Workloads = ad.Workloads.Values() return r } type ApplicationDetail struct { AppTypes Set DeployClusters Set DubboPorts Set DubboVersions Set Images Set RegisterClusters Set RegisterModes Set RPCProtocols Set SerialProtocols Set Workloads Set } func NewApplicationDetail() *ApplicationDetail { return &ApplicationDetail{ AppTypes: NewSet(), DeployClusters: NewSet(), DubboPorts: NewSet(), DubboVersions: NewSet(), Images: NewSet(), RegisterClusters: NewSet(), RegisterModes: NewSet(), RPCProtocols: NewSet(), SerialProtocols: NewSet(), Workloads: NewSet(), } } func (a *ApplicationDetail) MergeMetaData(metadata *mesh.MetaDataResource) { a.mergeServiceInfo(metadata) } func (a *ApplicationDetail) mergeServiceInfo(metadata *mesh.MetaDataResource) { for _, serviceInfo := range metadata.Spec.Services { a.DubboVersions.Add(fmt.Sprintf("dubbo %s", serviceInfo.Params[constants.ReleaseKey])) a.RPCProtocols.Add(serviceInfo.Protocol) a.SerialProtocols.Add(serviceInfo.Params[constants.SerializationKey]) } } func (a *ApplicationDetail) MergeDataplane(dataplane *mesh.DataplaneResource) { if work, ok := dataplane.Spec.Extensions[constants.WorkLoadKey]; ok && regexp.MustCompile(`^.*-\d+$`).MatchString(work) { a.AppTypes.Add(constants.Stateful) } else { a.AppTypes.Add(constants.Stateless) } inbounds := dataplane.Spec.Networking.Inbound for _, inbound := range inbounds { a.mergeInbound(inbound) } extensions := dataplane.Spec.Extensions a.mergeExtensions(extensions) } func (a *ApplicationDetail) mergeInbound(inbound *v1alpha1.Dataplane_Networking_Inbound) { a.DubboPorts.Add(strconv.Itoa(int(inbound.Port))) a.DeployClusters.Add(inbound.Tags[v1alpha1.ZoneTag]) } func (a *ApplicationDetail) mergeExtensions(extensions map[string]string) { a.Images.Add(extensions[dataplane.ExtensionsImageKey]) a.Workloads.Add(extensions[dataplane.ExtensionsWorkLoadKey]) } func (a *ApplicationDetail) GetRegistry(rt core_runtime.Runtime) { runtimeMode := rt.GetDeployMode() if runtimeMode == core.KubernetesMode { // In Kubernetes mode, registry cluster is the Kubernetes cluster itself a.RegisterClusters.Add(a.DeployClusters.Values()...) a.RegisterModes.Add("应用级", "接口级") } else if runtimeMode == core.HalfHostMode || runtimeMode == core.UniversalMode { // In half or universal mode, registry cluster is the zookeeper cluster or other registry center registryURL := rt.RegistryCenter().GetURL() registryCluster := registryURL.GetParam(constants.RemoteClientNameKey, "") a.RegisterClusters.Add(registryCluster) registryMode := registryURL.GetParam(constants.RegisterModeKey, constants.DefaultRegisterModeAll) if registryMode == constants.DefaultRegisterModeAll { a.RegisterModes.Add("应用级", "接口级") } else if registryCluster == constants.DefaultRegisterModeInstance { a.RegisterClusters.Add("应用级") } else if registryCluster == constants.DefaultRegisterModeInterface { a.RegisterClusters.Add("接口级") } } } // todo Application instance info type ApplicationTabInstanceInfoReq struct { AppName string `form:"appName"` PageReq } func NewApplicationTabInstanceInfoReq() *ApplicationTabInstanceInfoReq { return &ApplicationTabInstanceInfoReq{ PageReq: PageReq{ PageOffset: 0, PageSize: 15, }, } } type ApplicationTabInstanceInfoResp struct { AppName string `json:"appName"` CreateTime string `json:"createTime"` DeployState string `json:"deployState"` DeployClusters string `json:"deployClusters"` IP string `json:"ip"` Labels map[string]string `json:"labels"` Name string `json:"name"` RegisterCluster string `json:"registerCluster"` RegisterState string `json:"registerState"` RegisterTime string `json:"registerTime"` WorkloadName string `json:"workloadName"` } type ByApplicationInstanceName []*ApplicationTabInstanceInfoResp func (a ByApplicationInstanceName) Len() int { return len(a) } func (a ByApplicationInstanceName) Less(i, j int) bool { return a[i].Name < a[j].Name } func (a ByApplicationInstanceName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } func (a *ApplicationTabInstanceInfoResp) FromDataplaneResource(dataplane *mesh.DataplaneResource) *ApplicationTabInstanceInfoResp { // TODO: support more fields extensions := dataplane.Spec.Extensions a.mergeExtension(extensions) a.mergeMainDataplane(dataplane) return a } // nolint func (a *ApplicationTabInstanceInfoResp) mergeMainDataplane(dataplane *mesh.DataplaneResource) { a.AppName = dataplane.GetMeta().GetLabels()[v1alpha1.Application] a.CreateTime = dataplane.Meta.GetCreationTime().String() a.IP = dataplane.Spec.Networking.Address a.DeployClusters = dataplane.Spec.Networking.Inbound[0].Tags[v1alpha1.ZoneTag] a.Labels = dataplane.GetMeta().GetLabels() a.Name = dataplane.Meta.GetName() a.RegisterTime = a.CreateTime if a.RegisterTime != "" { a.RegisterState = "Registed" } else { a.RegisterState = "UnRegisted" } } func (a *ApplicationTabInstanceInfoResp) mergeExtension(extensions map[string]string) { a.WorkloadName = extensions[dataplane.ExtensionsWorkLoadKey] a.DeployState = extensions[dataplane.ExtensionsPodPhaseKey] } func (a *ApplicationTabInstanceInfoResp) GetRegistry(rt core_runtime.Runtime) { runtimeMode := rt.GetDeployMode() if runtimeMode == core.KubernetesMode { // In Kubernetes mode, registry cluster is the Kubernetes cluster itself a.RegisterCluster = a.DeployClusters } else if runtimeMode == core.HalfHostMode || runtimeMode == core.UniversalMode { // In half or universal mode, registry cluster is the zookeeper cluster or other registry center registryURL := rt.RegistryCenter().GetURL() registryCluster := registryURL.GetParam(constants.RegistryClusterKey, "") a.RegisterCluster = registryCluster } } // Todo Application Service type ApplicationServiceReq struct { AppName string `json:"appName"` } type ApplicationServiceResp struct { ConsumeNum int64 `json:"consumeNum"` ProvideNum int64 `json:"provideNum"` } type ApplicationServiceFormReq struct { AppName string `form:"appName"` Side string `form:"side"` PageReq } func NewApplicationServiceFormReq() *ApplicationServiceFormReq { return &ApplicationServiceFormReq{ PageReq: PageReq{ PageOffset: 0, PageSize: 15, }, } } type ApplicationServiceFormResp struct { ServiceName string `json:"serviceName"` VersionGroups []versionGroup `json:"versionGroups"` } type ByAppServiceFormName []*ApplicationServiceFormResp func (a ByAppServiceFormName) Len() int { return len(a) } func (a ByAppServiceFormName) Less(i, j int) bool { return a[i].ServiceName < a[j].ServiceName } func (a ByAppServiceFormName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } type versionGroup struct { Group string `json:"group"` Version string `json:"version"` } func NewApplicationServiceFormResp() *ApplicationServiceFormResp { return &ApplicationServiceFormResp{ ServiceName: "", VersionGroups: nil, } } func (a *ApplicationServiceFormResp) FromApplicationServiceForm(form *ApplicationServiceForm) error { a.ServiceName = form.ServiceName versionGroupList := make([]versionGroup, 0) for _, gv := range form.VersionGroups.Values() { var versionGroupInfo versionGroup if err := json.Unmarshal([]byte(gv), &versionGroupInfo); err != nil { return err } versionGroupList = append(versionGroupList, versionGroupInfo) } a.VersionGroups = versionGroupList return nil } type ApplicationServiceForm struct { ServiceName string VersionGroups Set } func NewApplicationServiceForm(serviceName string) *ApplicationServiceForm { return &ApplicationServiceForm{ ServiceName: serviceName, VersionGroups: NewSet(), } } func (a *ApplicationServiceForm) FromServiceInfo(serviceInfo *v1alpha1.ServiceInfo) error { versionGroupInfo := versionGroup{ Group: serviceInfo.Group, Version: serviceInfo.Version, } bytes, err := json.Marshal(versionGroupInfo) if err != nil { return err } a.VersionGroups.Add(string(bytes)) return nil } type ApplicationSearchReq struct { AppName string `form:"appName" json:"appName"` Keywords string `form:"keywords" json:"keywords"` PageReq } func NewApplicationSearchReq() *ApplicationSearchReq { return &ApplicationSearchReq{ PageReq: PageReq{ PageOffset: 0, PageSize: 15, }, } } type ApplicationSearchResp struct { AppName string `json:"appName"` DeployClusters []string `json:"deployClusters"` InstanceCount int64 `json:"instanceCount"` RegistryClusters []string `json:"registryClusters"` } func (a *ApplicationSearchResp) FromApplicationSearch(applicationSearch *ApplicationSearch) *ApplicationSearchResp { a.RegistryClusters = applicationSearch.RegistryClusters.Values() a.InstanceCount = applicationSearch.InstanceCount a.DeployClusters = applicationSearch.DeployClusters.Values() return a } type ByAppName []*ApplicationSearchResp func (a ByAppName) Len() int { return len(a) } func (a ByAppName) Less(i, j int) bool { return a[i].AppName < a[j].AppName } func (a ByAppName) Swap(i, j int) { a[i], a[j] = a[j], a[i] } // Todo Application Search type ApplicationSearch struct { AppName string DeployClusters Set InstanceCount int64 RegistryClusters Set } func NewApplicationSearch(appName string) *ApplicationSearch { return &ApplicationSearch{ AppName: appName, DeployClusters: NewSet(), InstanceCount: 0, RegistryClusters: NewSet(), } } func (a *ApplicationSearch) MergeDataplane(dataplane *mesh.DataplaneResource) { a.InstanceCount++ // merge inbounds inbounds := dataplane.Spec.Networking.Inbound for _, inbound := range inbounds { a.DeployClusters.Add(inbound.Tags[v1alpha1.ZoneTag]) } } func (a *ApplicationSearch) GetRegistry(rt core_runtime.Runtime) { runtimeMode := rt.GetDeployMode() if runtimeMode == core.KubernetesMode { // In Kubernetes mode, registry cluster is the Kubernetes cluster itself a.RegistryClusters.Add(a.DeployClusters.Values()...) } else if runtimeMode == core.HalfHostMode || runtimeMode == core.UniversalMode { // In half or universal mode, registry cluster is the zookeeper cluster or other registry center registryURL := rt.RegistryCenter().GetURL() registryCluster := registryURL.GetParam(constants.RegistryClusterKey, registryURL.Address()) a.RegistryClusters.Add(registryCluster) } } type FlowWeightSet struct { Weight int32 `json:"weight"` Scope []ParamMatch `json:"scope,omitempty"` } type GraySet struct { EnvName string `json:"name,omitempty"` Scope []ParamMatch `json:"scope,omitempty"` }