|  | /* | 
|  | * 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 ( | 
|  | gxset "github.com/dubbogo/gost/container/set" | 
|  | ) | 
|  |  | 
|  | import ( | 
|  | "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1" | 
|  | mesh_proto "github.com/apache/dubbo-kubernetes/api/mesh/v1alpha1" | 
|  | "github.com/apache/dubbo-kubernetes/pkg/core/managers/apis/dataplane" | 
|  | "github.com/apache/dubbo-kubernetes/pkg/core/resources/apis/mesh" | 
|  | "github.com/apache/dubbo-kubernetes/pkg/core/resources/model" | 
|  | ) | 
|  |  | 
|  | type SearchInstanceReq struct { | 
|  | AppName  string `form:"appName"` | 
|  | Keywords string `form:"keywords"` | 
|  | PageReq | 
|  | } | 
|  |  | 
|  | func NewSearchInstanceReq() *SearchInstanceReq { | 
|  | return &SearchInstanceReq{ | 
|  | PageReq: PageReq{PageSize: 15}, | 
|  | } | 
|  | } | 
|  |  | 
|  | type InstanceDetailReq struct { | 
|  | InstanceName string `form:"instanceName"` | 
|  | } | 
|  |  | 
|  | type SearchPaginationResult struct { | 
|  | List     any               `json:"list"` | 
|  | PageInfo *model.Pagination `json:"pageInfo"` | 
|  | } | 
|  |  | 
|  | func NewSearchPaginationResult() *SearchPaginationResult { | 
|  | return &SearchPaginationResult{} | 
|  | } | 
|  |  | 
|  | type SearchInstanceResp struct { | 
|  | Ip                  string            `json:"ip"` | 
|  | Name                string            `json:"name"` | 
|  | WorkloadName        string            `json:"workloadName"` | 
|  | AppName             string            `json:"appName"` | 
|  | DeployState         string            `json:"deployState"` | 
|  | DeployCluster       string            `json:"deployCluster"` | 
|  | RegisterState       string            `json:"registerState"` | 
|  | RegisterClustersSet *gxset.HashSet    `json:"-"` | 
|  | RegisterClusters    []string          `json:"registerClusters"` | 
|  | CreateTime          string            `json:"createTime"` | 
|  | RegisterTime        string            `json:"registerTime"` // TODO: not converted | 
|  | Labels              map[string]string `json:"labels"` | 
|  | } | 
|  |  | 
|  | func NewSearchInstanceResp() *SearchInstanceResp { | 
|  | return &SearchInstanceResp{ | 
|  | RegisterClustersSet: gxset.NewSet(), | 
|  | RegisterClusters:    make([]string, 0), | 
|  | } | 
|  | } | 
|  |  | 
|  | func (r *SearchInstanceResp) FromDataplaneResource(dr *mesh.DataplaneResource) *SearchInstanceResp { | 
|  | // TODO: support more fields | 
|  | r.Ip = dr.GetIP() | 
|  | meta := dr.GetMeta() | 
|  | r.Name = meta.GetName() | 
|  | r.CreateTime = meta.GetCreationTime().String() | 
|  | r.RegisterTime = r.CreateTime // TODO: separate createTime and RegisterTime | 
|  | cluster := dr.Spec.Networking.Inbound[0].Tags[v1alpha1.ZoneTag] | 
|  | r.RegisterClustersSet.Add(cluster) | 
|  | for _, c := range r.RegisterClustersSet.Values() { | 
|  | r.RegisterClusters = append(r.RegisterClusters, c.(string)) | 
|  | } | 
|  | r.DeployCluster = cluster | 
|  | if r.RegisterTime != "" { | 
|  | r.RegisterState = "Registed" | 
|  | } else { | 
|  | r.RegisterState = "UnRegisted" | 
|  | } | 
|  | // label conversion | 
|  | r.Labels = meta.GetLabels() | 
|  | // spec conversion | 
|  | spec := dr.Spec | 
|  | { | 
|  | statusValue := spec.Extensions[dataplane.ExtensionsPodPhaseKey] | 
|  | if v, ok := spec.Extensions[dataplane.ExtensionsPodStatusKey]; ok { | 
|  | statusValue = v | 
|  | } | 
|  | if v, ok := spec.Extensions[dataplane.ExtensionsContainerStatusReasonKey]; ok { | 
|  | statusValue = v | 
|  | } | 
|  | r.DeployState = statusValue | 
|  | r.WorkloadName = spec.Extensions[dataplane.ExtensionsWorkLoadKey] | 
|  | // name field source is different between universal and k8s mode | 
|  | r.AppName = spec.Extensions[mesh_proto.Application] | 
|  | if r.AppName == "" { | 
|  | for _, inbound := range spec.Networking.Inbound { | 
|  | r.AppName = inbound.Tags[v1alpha1.AppTag] | 
|  | } | 
|  | } | 
|  | } | 
|  | return r | 
|  | } | 
|  |  | 
|  | type State struct { | 
|  | Label string `json:"label"` | 
|  | Level string `json:"level"` | 
|  | Tip   string `json:"tip"` | 
|  | Value string `json:"value"` | 
|  | } | 
|  |  | 
|  | type InstanceDetailResp struct { | 
|  | RpcPort          int               `json:"rpcPort"` | 
|  | Ip               string            `json:"ip"` | 
|  | AppName          string            `json:"appName"` | 
|  | WorkloadName     string            `json:"workloadName"` | 
|  | Labels           map[string]string `json:"labels"` | 
|  | CreateTime       string            `json:"createTime"` | 
|  | ReadyTime        string            `json:"readyTime"` | 
|  | RegisterTime     string            `json:"registerTime"` | 
|  | RegisterClusters []string          `json:"registerClusters"` | 
|  | DeployCluster    string            `json:"deployCluster"` | 
|  | DeployState      string            `json:"deployState"` | 
|  | RegisterState    string            `json:"registerState"` | 
|  | Node             string            `json:"node"` | 
|  | Image            string            `json:"image"` | 
|  | Probes           ProbeStruct       `json:"probes"` | 
|  | Tags             map[string]string `json:"tags"` | 
|  | } | 
|  |  | 
|  | type ProbeStruct struct { | 
|  | StartupProbe   StartupProbe   `json:"startupProbe"` | 
|  | ReadinessProbe ReadinessProbe `json:"readinessProbe"` | 
|  | LivenessProbe  LivenessProbe  `json:"livenessProbe"` | 
|  | } | 
|  |  | 
|  | type StartupProbe struct { | 
|  | Type string `json:"type"` | 
|  | Port int    `json:"port"` | 
|  | Open bool   `json:"open"` | 
|  | } | 
|  | type ReadinessProbe struct { | 
|  | Type string `json:"type"` | 
|  | Port int    `json:"port"` | 
|  | Open bool   `json:"open"` | 
|  | } | 
|  | type LivenessProbe struct { | 
|  | Type string `json:"type"` | 
|  | Port int    `json:"port"` | 
|  | Open bool   `json:"open"` | 
|  | } | 
|  |  | 
|  | func (r *InstanceDetailResp) FromInstanceDetail(id *InstanceDetail) *InstanceDetailResp { | 
|  | r.AppName = id.AppName | 
|  | r.RpcPort = id.RpcPort | 
|  | r.Ip = id.Ip | 
|  | r.WorkloadName = id.WorkloadName | 
|  | r.Labels = id.Labels | 
|  | r.CreateTime = id.CreateTime | 
|  | r.ReadyTime = id.ReadyTime | 
|  | r.RegisterTime = id.RegisterTime | 
|  | r.RegisterClusters = id.RegisterClusters.Values() | 
|  | r.DeployCluster = id.DeployCluster | 
|  | r.DeployCluster = id.DeployCluster | 
|  | r.DeployState = id.DeployState | 
|  | r.Node = id.Node | 
|  | r.Image = id.Image | 
|  | r.Tags = id.Tags | 
|  | r.RegisterState = id.RegisterState | 
|  | r.Probes = id.Probes | 
|  | return r | 
|  | } | 
|  |  | 
|  | type InstanceDetail struct { | 
|  | RpcPort          int | 
|  | Ip               string | 
|  | AppName          string | 
|  | WorkloadName     string | 
|  | Labels           map[string]string | 
|  | CreateTime       string | 
|  | ReadyTime        string | 
|  | RegisterTime     string | 
|  | RegisterState    string | 
|  | RegisterClusters Set | 
|  | DeployCluster    string | 
|  | DeployState      string | 
|  | Node             string | 
|  | Image            string | 
|  | Tags             map[string]string | 
|  | Probes           ProbeStruct | 
|  | } | 
|  |  | 
|  | func NewInstanceDetail() *InstanceDetail { | 
|  | return &InstanceDetail{ | 
|  | RpcPort:          -1, | 
|  | Ip:               "", | 
|  | AppName:          "", | 
|  | WorkloadName:     "", | 
|  | Labels:           nil, | 
|  | CreateTime:       "", | 
|  | ReadyTime:        "", | 
|  | RegisterTime:     "", | 
|  | RegisterClusters: NewSet(), | 
|  | DeployCluster:    "", | 
|  | Node:             "", | 
|  | Image:            "", | 
|  | } | 
|  | } | 
|  |  | 
|  | func (a *InstanceDetail) Merge(dataplane *mesh.DataplaneResource) { | 
|  | // TODO: support more fields | 
|  | inbounds := dataplane.Spec.Networking.Inbound | 
|  | for _, inbound := range inbounds { | 
|  | a.mergeInbound(inbound) | 
|  | } | 
|  | meta := dataplane.Meta | 
|  | a.mergeMeta(meta) | 
|  | extensions := dataplane.Spec.Extensions | 
|  | a.mergeExtensions(extensions) | 
|  | probes := dataplane.Spec.Probes | 
|  | a.mergeProbes(probes) | 
|  |  | 
|  | a.Ip = dataplane.GetIP() | 
|  | if a.RegisterTime != "" { | 
|  | a.RegisterState = "Registed" | 
|  | } else { | 
|  | a.RegisterState = "UnRegisted" | 
|  | } | 
|  | } | 
|  |  | 
|  | func (a *InstanceDetail) mergeInbound(inbound *v1alpha1.Dataplane_Networking_Inbound) { | 
|  | a.RpcPort = int(inbound.Port) | 
|  | a.RegisterClusters.Add(inbound.Tags[v1alpha1.ZoneTag]) | 
|  | for _, deployCluster := range a.RegisterClusters.Values() { | 
|  | a.DeployCluster = deployCluster // TODO: separate deployCluster and registerCluster | 
|  | } | 
|  | a.Tags = inbound.Tags | 
|  | if a.AppName == "" { | 
|  | a.AppName = inbound.Tags[v1alpha1.AppTag] | 
|  | } | 
|  | } | 
|  |  | 
|  | func (a *InstanceDetail) mergeExtensions(extensions map[string]string) { | 
|  | image := extensions[dataplane.ExtensionsImageKey] | 
|  | a.Image = image | 
|  | if a.AppName == "" { | 
|  | a.AppName = extensions[mesh_proto.Application] | 
|  | } | 
|  | a.WorkloadName = extensions[dataplane.ExtensionsWorkLoadKey] | 
|  | a.DeployState = extensions[dataplane.ExtensionsPodPhaseKey] | 
|  | a.Node = extensions[dataplane.ExtensionsNodeNameKey] | 
|  | } | 
|  |  | 
|  | func (a *InstanceDetail) mergeMeta(meta model.ResourceMeta) { | 
|  | a.CreateTime = meta.GetCreationTime().String() | 
|  | a.RegisterTime = meta.GetModificationTime().String() // Not sure if it's the right field | 
|  | a.ReadyTime = a.RegisterTime | 
|  | // TODO: separate createTime , RegisterTime and ReadyTime | 
|  | a.Labels = meta.GetLabels() | 
|  | } | 
|  |  | 
|  | func (a *InstanceDetail) mergeProbes(probes *mesh_proto.Dataplane_Probes) { | 
|  | if probes == nil { | 
|  | return | 
|  | } | 
|  | portStartup := probes.Endpoints[0].InboundPort | 
|  | portReadiness := probes.Endpoints[1].InboundPort | 
|  | portLiveness := probes.Endpoints[2].InboundPort | 
|  | a.Probes = ProbeStruct{ | 
|  | StartupProbe: StartupProbe{ | 
|  | Type: "HTTP", // TODO: support more scheme | 
|  |  | 
|  | Port: int(portStartup), | 
|  | Open: true, | 
|  | }, | 
|  | ReadinessProbe: ReadinessProbe{ | 
|  | Type: "HTTP", // TODO: support more scheme | 
|  | Port: int(portReadiness), | 
|  | Open: true, | 
|  | }, | 
|  | LivenessProbe: LivenessProbe{ | 
|  | Type: "HTTP", // TODO: support more scheme | 
|  | Port: int(portLiveness), | 
|  | Open: true, | 
|  | }, | 
|  | } | 
|  | } |