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