f81e5bce1759323cd6bca325b865107a2d5986de
[ealt-edge.git] / mep / mepserver / mp1 / util / meputil.go
1 /*
2  * Copyright 2020 Huawei Technologies Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16
17 package util
18
19 import (
20         "bytes"
21         "context"
22         "encoding/json"
23         "fmt"
24         "net/http"
25         "net/url"
26         "strconv"
27         "strings"
28
29         "github.com/apache/servicecomb-service-center/pkg/log"
30         "github.com/apache/servicecomb-service-center/pkg/rest"
31         "github.com/apache/servicecomb-service-center/pkg/util"
32         "github.com/apache/servicecomb-service-center/server/core"
33         "github.com/apache/servicecomb-service-center/server/core/backend"
34         "github.com/apache/servicecomb-service-center/server/core/proto"
35         svcerror "github.com/apache/servicecomb-service-center/server/error"
36         "github.com/apache/servicecomb-service-center/server/plugin/pkg/registry"
37         "github.com/apache/servicecomb-service-center/server/rest/controller"
38         svcutil "github.com/apache/servicecomb-service-center/server/service/util"
39 )
40
41 func InfoToProperties(properties map[string]string, key string, value string) {
42         if value != "" {
43                 properties[key] = value
44         }
45 }
46
47 func JsonTextToObj(jsonText string) (interface{}, error) {
48         data := []byte(jsonText)
49         var jsonMap interface{}
50         decoder := json.NewDecoder(bytes.NewReader(data))
51         err := decoder.Decode(&jsonMap)
52         if err != nil {
53                 return nil, err
54         }
55         return jsonMap, nil
56 }
57
58 func GetHostPort(uri string) (string, int) {
59         idx := strings.LastIndex(uri, ":")
60         domain := uri
61         port := 0
62         var err error
63         if idx > 0 {
64                 port, err = strconv.Atoi(uri[idx+1:])
65                 if err != nil {
66                         port = 0
67                 }
68                 domain = uri[:idx]
69         }
70         return domain, port
71 }
72
73 func GetHTTPTags(r *http.Request) (url.Values, []string) {
74         var ids []string
75         query := r.URL.Query()
76         keys := query.Get("tags")
77         if len(keys) > 0 {
78                 ids = strings.Split(keys, ",")
79         }
80
81         return query, ids
82 }
83
84 func GetFindParam(r *http.Request) (context.Context, *proto.FindInstancesRequest, url.Values) {
85
86         query, ids := GetHTTPTags(r)
87
88         req := &proto.FindInstancesRequest{
89                 ConsumerServiceId: r.Header.Get("X-ConsumerId"),
90                 AppId:             query.Get("instance_id"),
91                 ServiceName:       query.Get("ser_name"),
92                 VersionRule:       query.Get("version"),
93                 Environment:       query.Get("env"),
94                 Tags:              ids,
95         }
96
97         if req.AppId == "" {
98                 req.AppId = "default"
99         }
100         if req.VersionRule == "" {
101                 req.VersionRule = "latest"
102         }
103         ctx := util.SetTargetDomainProject(r.Context(), r.Header.Get("X-Domain-Name"), query.Get(":project"))
104         return ctx, req, query
105 }
106
107 //send http response
108 func WriteHTTPResponse(w http.ResponseWriter, resp *proto.Response, obj interface{}) {
109         if resp != nil && resp.GetCode() != proto.Response_SUCCESS {
110                 controller.WriteError(w, resp.GetCode(), resp.GetMessage())
111                 return
112         }
113         if obj == nil {
114                 w.Header().Set(rest.HEADER_RESPONSE_STATUS, strconv.Itoa(http.StatusOK))
115                 w.Header().Set(rest.HEADER_CONTENT_TYPE, rest.CONTENT_TYPE_TEXT)
116                 w.WriteHeader(http.StatusOK)
117                 return
118         }
119
120         objJSON, err := json.Marshal(obj)
121         if err != nil {
122                 controller.WriteError(w, svcerror.ErrInternal, err.Error())
123                 return
124         }
125         w.Header().Set(rest.HEADER_RESPONSE_STATUS, strconv.Itoa(http.StatusOK))
126         w.Header().Set(rest.HEADER_CONTENT_TYPE, rest.CONTENT_TYPE_JSON)
127         w.WriteHeader(http.StatusCreated)
128         _, err = fmt.Fprintln(w, util.BytesToStringWithNoCopy(objJSON))
129         if err != nil {
130                 return
131         }
132 }
133
134 func WriteResponse(w http.ResponseWriter, resp *proto.Response, obj interface{}) {
135         if resp != nil && resp.GetCode() != proto.Response_SUCCESS {
136                 controller.WriteError(w, resp.GetCode(), resp.GetMessage())
137                 return
138         }
139         if obj == nil {
140                 w.Header().Set(rest.HEADER_RESPONSE_STATUS, strconv.Itoa(http.StatusOK))
141                 w.Header().Set(rest.HEADER_CONTENT_TYPE, rest.CONTENT_TYPE_TEXT)
142                 w.WriteHeader(http.StatusOK)
143                 return
144         }
145
146         objJSON, err := json.Marshal(obj)
147         if err != nil {
148                 controller.WriteError(w, svcerror.ErrInternal, err.Error())
149                 return
150         }
151         w.Header().Set(rest.HEADER_RESPONSE_STATUS, strconv.Itoa(http.StatusOK))
152         w.Header().Set(rest.HEADER_CONTENT_TYPE, rest.CONTENT_TYPE_JSON)
153         w.WriteHeader(http.StatusOK)
154         _, err = fmt.Fprintln(w, util.BytesToStringWithNoCopy(objJSON))
155         if err != nil {
156                 return
157         }
158 }
159
160 func HttpErrResponse(w http.ResponseWriter, statusCode int, obj interface{}) {
161         if obj == nil {
162                 w.Header().Set(rest.HEADER_RESPONSE_STATUS, strconv.Itoa(statusCode))
163                 w.Header().Set(rest.HEADER_CONTENT_TYPE, rest.CONTENT_TYPE_TEXT)
164                 w.WriteHeader(statusCode)
165                 return
166         }
167
168         objJSON, err := json.Marshal(obj)
169         if err != nil {
170                 log.Errorf(err, "json marshal object fail")
171                 return
172         }
173         w.Header().Set(rest.HEADER_RESPONSE_STATUS, strconv.Itoa(http.StatusOK))
174         w.Header().Set(rest.HEADER_CONTENT_TYPE, rest.CONTENT_TYPE_JSON)
175         w.WriteHeader(statusCode)
176         _, err = fmt.Fprintln(w, util.BytesToStringWithNoCopy(objJSON))
177         if err != nil {
178                 log.Errorf(err, "send http response fail")
179         }
180 }
181
182 // heartbeat use put to update a service register info
183 func Heartbeat(ctx context.Context, mp1SvcId string) error {
184         serviceID := mp1SvcId[:len(mp1SvcId)/2]
185         instanceID := mp1SvcId[len(mp1SvcId)/2:]
186         req := &proto.HeartbeatRequest{
187                 ServiceId:  serviceID,
188                 InstanceId: instanceID,
189         }
190         _, err := core.InstanceAPI.Heartbeat(ctx, req)
191         return err
192 }
193
194 func GetServiceInstance(ctx context.Context, serviceId string) (*proto.MicroServiceInstance, error) {
195         domainProjet := util.ParseDomainProject(ctx)
196         serviceID := serviceId[:len(serviceId)/2]
197         instanceID := serviceId[len(serviceId)/2:]
198         instance, err := svcutil.GetInstance(ctx, domainProjet, serviceID, instanceID)
199         if err != nil {
200                 return nil, err
201         }
202         if instance == nil {
203                 err = fmt.Errorf("domainProjet %s sservice Id %s not exist", domainProjet, serviceID)
204         }
205         return instance, err
206 }
207
208 func FindInstanceByKey(result url.Values) (*proto.FindInstancesResponse, error) {
209         serCategoryId := result.Get("ser_category_id")
210         scopeOfLocality := result.Get("scope_of_locality")
211         consumedLocalOnly := result.Get("consumed_local_only")
212         isLocal := result.Get("is_local")
213         isQueryAllSvc := serCategoryId == "" && scopeOfLocality == "" && consumedLocalOnly == "" && isLocal == ""
214
215         opts := []registry.PluginOp{
216                 registry.OpGet(registry.WithStrKey("/cse-sr/inst/files///"), registry.WithPrefix()),
217         }
218         resp, err := backend.Registry().TxnWithCmp(context.Background(), opts, nil, nil)
219         if err != nil {
220                 return nil, fmt.Errorf("query from etch error")
221         }
222         var findResp []*proto.MicroServiceInstance
223         for _, value := range resp.Kvs {
224                 var instance map[string]interface{}
225                 err = json.Unmarshal(value.Value, &instance)
226                 if err != nil {
227                         return nil, fmt.Errorf("string convert to instance failed")
228                 }
229                 dci := &proto.DataCenterInfo{Name: "", Region: "", AvailableZone: ""}
230                 instance["datacenterinfo"] = dci
231                 var message []byte
232                 message, err = json.Marshal(&instance)
233                 if err != nil {
234                         log.Errorf(err, "Instance convert to string failed!")
235                 }
236                 var ins *proto.MicroServiceInstance
237                 err = json.Unmarshal(message, &ins)
238                 if err != nil {
239                         log.Errorf(err, "String convert to MicroServiceInstance failed!")
240                 }
241                 property := ins.Properties
242                 if isQueryAllSvc && property != nil {
243                         findResp = append(findResp, ins)
244                 } else if strings.EqualFold(property["serCategory/id"], serCategoryId) ||
245                         strings.EqualFold(property["ConsumedLocalOnly"], consumedLocalOnly) ||
246                         strings.EqualFold(property["ScopeOfLocality"], scopeOfLocality) ||
247                         strings.EqualFold(property["IsLocal"], isLocal) {
248                         findResp = append(findResp, ins)
249                 }
250         }
251         if len(findResp) == 0 {
252                 return nil, fmt.Errorf("service not found")
253         }
254         response := &proto.Response{Code: 0, Message: ""}
255         ret := &proto.FindInstancesResponse{Response: response, Instances: findResp}
256         return ret, nil
257 }
258
259 func SetMapValue(theMap map[string]interface{}, key string, val interface{}) {
260         mapValue, ok := theMap[key]
261         if !ok || mapValue == nil {
262                 theMap[key] = val
263         }
264 }
265