Code optimization for Optimization
[ealt-edge.git] / mep / mepserver / mp1 / plan_register_svc.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 mp1
18
19 import (
20         "context"
21         "encoding/json"
22         "fmt"
23         "io/ioutil"
24         "net/http"
25
26         "github.com/apache/servicecomb-service-center/pkg/log"
27         "github.com/apache/servicecomb-service-center/pkg/util"
28         "github.com/apache/servicecomb-service-center/server/core"
29         "github.com/apache/servicecomb-service-center/server/core/proto"
30         svcerr "github.com/apache/servicecomb-service-center/server/error"
31
32         "mepserver/mp1/arch/workspace"
33         "mepserver/mp1/models"
34         meputil "mepserver/mp1/util"
35 )
36
37 type DecodeRestReq struct {
38         workspace.TaskBase
39         R             *http.Request   `json:"r,in"`
40         Ctx           context.Context `json:"ctx,out"`
41         AppInstanceId string          `json:"appInstanceId,out"`
42         SubscribeId   string          `json:"subscribeId,out"`
43         ServiceId     string          `json:"serviceId,out"`
44         RestBody      interface{}     `json:"restBody,out"`
45 }
46
47 //service request handler
48 func (t *DecodeRestReq) OnRequest(data string) workspace.TaskCode {
49         t.GetParam(t.R)
50         err := t.ParseBody(t.R)
51         if err != nil {
52                 log.Error("parse rest body failed", err)
53         }
54         return workspace.TaskFinish
55 }
56
57 func (t *DecodeRestReq) ParseBody(r *http.Request) error {
58         if t.RestBody == nil {
59                 return nil
60         }
61         msg, err := ioutil.ReadAll(r.Body)
62         if err != nil {
63                 log.Error("read body failed", err)
64                 t.SetFirstErrorCode(SerErrFailBase, err.Error())
65                 return err
66         }
67
68         newMsg, err := t.checkParam(msg)
69         if err != nil {
70                 log.Error("check Param failed", err)
71                 t.SetFirstErrorCode(SerErrFailBase, err.Error())
72                 return err
73         }
74
75         err = json.Unmarshal(newMsg, t.RestBody)
76         if err != nil {
77                 log.Errorf(err, "invalid json: %s", util.BytesToStringWithNoCopy(newMsg))
78                 t.SetFirstErrorCode(SerErrFailBase, err.Error())
79                 return err
80         }
81         return nil
82
83 }
84
85 func (t *DecodeRestReq) checkParam(msg []byte) ([]byte, error) {
86
87         var temp map[string]interface{}
88         err := json.Unmarshal(msg, &temp)
89         if err != nil {
90                 log.Errorf(err, "invalid json to map: %s", util.BytesToStringWithNoCopy(msg))
91                 t.SetFirstErrorCode(SerErrFailBase, err.Error())
92                 return nil, err
93         }
94
95         meputil.SetMapValue(temp, "consumedLocalOnly", true)
96         meputil.SetMapValue(temp, "isLocal", true)
97         meputil.SetMapValue(temp, "scopeOfLocality", "MEC_HOST")
98
99         msg, err = json.Marshal(&temp)
100         if err != nil {
101                 log.Errorf(err, "invalid map to json")
102                 t.SetFirstErrorCode(SerErrFailBase, err.Error())
103                 return nil, err
104         }
105
106         return msg, nil
107 }
108
109 func (t *DecodeRestReq) WithBody(body interface{}) *DecodeRestReq {
110         t.RestBody = body
111         return t
112 }
113
114 func (t *DecodeRestReq) GetParam(r *http.Request) {
115         query, _ := meputil.GetHTTPTags(r)
116         t.AppInstanceId = query.Get(":appInstanceId")
117         t.SubscribeId = query.Get(":subscriptionId")
118         t.ServiceId = query.Get(":serviceId")
119         t.Ctx = util.SetTargetDomainProject(r.Context(), r.Header.Get("X-Domain-Name"), query.Get(":project"))
120 }
121
122 type RegisterServiceId struct {
123         HttpErrInf *proto.Response `json:"httpErrInf,out"`
124         workspace.TaskBase
125         Ctx       context.Context `json:"ctx,in"`
126         ServiceId string          `json:"serviceId,out"`
127         RestBody  interface{}     `json:"restBody,in"`
128 }
129
130 func (t *RegisterServiceId) OnRequest(data string) workspace.TaskCode {
131
132         serviceInfo, ok := t.RestBody.(*models.ServiceInfo)
133         if !ok {
134                 t.SetFirstErrorCode(1, "restbody failed")
135                 return workspace.TaskFinish
136         }
137         req := &proto.CreateServiceRequest{}
138         serviceInfo.ToServiceRequest(req)
139         resp, err := core.ServiceAPI.Create(t.Ctx, req)
140         if err != nil {
141                 log.Errorf(err, "Service Center ServiceAPI.Create fail: %s!", err.Error())
142                 t.SetFirstErrorCode(1, err.Error())
143                 return workspace.TaskFinish
144         }
145
146         if resp.ServiceId == "" {
147                 t.HttpErrInf = resp.Response
148                 log.Warn("Service id empty.")
149         }
150         t.ServiceId = resp.ServiceId
151         return workspace.TaskFinish
152 }
153
154 type RegisterServiceInst struct {
155         HttpErrInf *proto.Response `json:"httpErrInf,out"`
156         workspace.TaskBase
157         W             http.ResponseWriter `json:"w,in"`
158         Ctx           context.Context     `json:"ctx,in"`
159         AppInstanceId string              `json:"appInstanceId,in"`
160         ServiceId     string              `json:"serviceId,in"`
161         InstanceId    string              `json:"instanceId,out"`
162         RestBody      interface{}         `json:"restBody,in"`
163         HttpRsp       interface{}         `json:"httpRsp,out"`
164 }
165
166 //request service registry handling
167 func (t *RegisterServiceInst) OnRequest(data string) workspace.TaskCode {
168         serviceInfo, ok := t.RestBody.(*models.ServiceInfo)
169         if !ok {
170                 t.SetFirstErrorCode(1, "restbody failed")
171                 return workspace.TaskFinish
172         }
173         req := &proto.RegisterInstanceRequest{}
174         serviceInfo.ToRegisterInstance(req)
175         req.Instance.ServiceId = t.ServiceId
176         req.Instance.Properties["appInstanceId"] = t.AppInstanceId
177
178         //Call service comb for instance register
179         resp, err := core.InstanceAPI.Register(t.Ctx, req)
180         if err != nil {
181                 log.Errorf(err, "RegisterInstance fail: %s", t.ServiceId)
182                 t.HttpErrInf = &proto.Response{}
183                 t.HttpErrInf.Code = svcerr.ErrForbidden
184                 t.HttpErrInf.Message = err.Error()
185                 return workspace.TaskFinish
186         }
187         t.InstanceId = resp.InstanceId
188
189         //build response serviceComb use serviceId + InstanceId to mark a service instance
190         mp1SerId := t.ServiceId + t.InstanceId
191         serviceInfo.SerInstanceId = mp1SerId
192         t.HttpRsp = serviceInfo
193
194         location := fmt.Sprintf("/mep/mp1/v1/services/%s", mp1SerId)
195         t.W.Header().Set("Location", location)
196         return workspace.TaskFinish
197 }