NONRTRIC-946: Add support for Kong routes
[nonrtric/plt/sme.git] / servicemanager / internal / invokermanagement / invokermanagement.go
1 // -
2 //   ========================LICENSE_START=================================
3 //   O-RAN-SC
4 //   %%
5 //   Copyright (C) 2023-2024: OpenInfra Foundation Europe
6 //   %%
7 //   Licensed under the Apache License, Version 2.0 (the "License");
8 //   you may not use this file except in compliance with the License.
9 //   You may obtain a copy of the License at
10 //
11 //        http://www.apache.org/licenses/LICENSE-2.0
12 //
13 //   Unless required by applicable law or agreed to in writing, software
14 //   distributed under the License is distributed on an "AS IS" BASIS,
15 //   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 //   See the License for the specific language governing permissions and
17 //   limitations under the License.
18 //   ========================LICENSE_END===================================
19 //
20
21 package invokermanagement
22
23 import (
24         "context"
25         "fmt"
26         "net/http"
27         "path"
28
29         "oransc.org/nonrtric/servicemanager/internal/common29122"
30         invokerapi "oransc.org/nonrtric/servicemanager/internal/invokermanagementapi"
31
32         echo "github.com/labstack/echo/v4"
33         log "github.com/sirupsen/logrus"
34 )
35
36 type InvokerManager struct {
37         CapifProtocol string
38         CapifIPv4     common29122.Ipv4Addr
39         CapifPort     common29122.Port
40 }
41
42 // Creates a manager that implements both the InvokerRegister and the invokermanagementapi.ServerInterface interfaces.
43 func NewInvokerManager(capifProtocol string, capifIPv4 common29122.Ipv4Addr, capifPort common29122.Port) *InvokerManager {
44         return &InvokerManager{
45                 CapifProtocol: capifProtocol,
46                 CapifIPv4:     capifIPv4,
47                 CapifPort:     capifPort,
48         }
49 }
50
51 // Creates a new individual API Invoker profile.
52 func (im *InvokerManager) PostOnboardedInvokers(ctx echo.Context) error {
53         log.Trace("entering PostOnboardedInvokers")
54
55         var newInvoker invokerapi.APIInvokerEnrolmentDetails
56         errMsg := "Unable to onboard invoker due to %s"
57         if err := ctx.Bind(&newInvoker); err != nil {
58                 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, "invalid format for invoker"))
59         }
60
61         capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-invoker-management/v1/", im.CapifProtocol, im.CapifIPv4, im.CapifPort)
62         client, err := invokerapi.NewClientWithResponses(capifcoreUrl)
63         if err != nil {
64                 return err
65         }
66
67         var (
68                 ctxHandler context.Context
69                 cancel     context.CancelFunc
70         )
71         ctxHandler, cancel = context.WithCancel(context.Background())
72         defer cancel()
73
74         postRegistrationsJSONRequestBody := invokerapi.PostOnboardedInvokersJSONRequestBody(newInvoker)
75
76         var rspInvoker *invokerapi.PostOnboardedInvokersResponse
77         rspInvoker, err = client.PostOnboardedInvokersWithResponse(ctxHandler, postRegistrationsJSONRequestBody)
78
79         if err != nil {
80                 msg := err.Error()
81                 log.Errorf("error on PostOnboardedInvokersWithResponse %s", msg)
82                 return sendCoreError(ctx, http.StatusInternalServerError, msg)
83         }
84
85         if rspInvoker.StatusCode() != http.StatusCreated {
86                 msg := string(rspInvoker.Body)
87                 log.Errorf("error on PostOnboardedInvokersWithResponse %s", msg)
88                 return sendCoreError(ctx, rspInvoker.StatusCode(), msg)
89         }
90
91         rspAPIProviderEnrolmentDetails := *rspInvoker.JSON201
92         apiInvokerId := *rspAPIProviderEnrolmentDetails.ApiInvokerId
93
94         uri := ctx.Request().Host + ctx.Request().URL.String()
95         ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, apiInvokerId))
96         err = ctx.JSON(http.StatusCreated, rspAPIProviderEnrolmentDetails)
97         if err != nil {
98                 // Something really bad happened, tell Echo that our handler failed
99                 return err
100         }
101
102         return nil
103 }
104
105 // Deletes an individual API Invoker.
106 func (im *InvokerManager) DeleteOnboardedInvokersOnboardingId(ctx echo.Context, onboardingId string) error {
107         log.Tracef("entering DeleteOnboardedInvokersOnboardingId onboardingId %s", onboardingId)
108
109         capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-invoker-management/v1/", im.CapifProtocol, im.CapifIPv4, im.CapifPort)
110         client, err := invokerapi.NewClientWithResponses(capifcoreUrl)
111         if err != nil {
112                 return err
113         }
114
115         var (
116                 ctxHandler context.Context
117                 cancel     context.CancelFunc
118         )
119         ctxHandler, cancel = context.WithCancel(context.Background())
120         defer cancel()
121
122         _, err = client.DeleteOnboardedInvokersOnboardingId(ctxHandler, onboardingId)
123
124         if err != nil {
125                 msg := err.Error()
126                 log.Errorf("error on DeleteOnboardedInvokersOnboardingId %s", msg)
127                 return sendCoreError(ctx, http.StatusInternalServerError, msg)
128         }
129
130         return ctx.NoContent(http.StatusNoContent)
131 }
132
133
134 // Updates an individual API invoker details.
135 func (im *InvokerManager) PutOnboardedInvokersOnboardingId(ctx echo.Context, onboardingId string) error {
136         log.Tracef("entering DeleteOnboardedInvokersOnboardingId onboardingId %s", onboardingId)
137
138         var invoker invokerapi.APIInvokerEnrolmentDetails
139         errMsg := "Unable to update invoker due to %s"
140         if err := ctx.Bind(&invoker); err != nil {
141                 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, "invalid format for invoker"))
142         }
143
144         capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-invoker-management/v1/", im.CapifProtocol, im.CapifIPv4, im.CapifPort)
145         client, err := invokerapi.NewClientWithResponses(capifcoreUrl)
146         if err != nil {
147                 return err
148         }
149
150         var (
151                 ctxHandler context.Context
152                 cancel     context.CancelFunc
153         )
154         ctxHandler, cancel = context.WithCancel(context.Background())
155         defer cancel()
156
157         putRegistrationsJSONRequestBody := invokerapi.PutOnboardedInvokersOnboardingIdJSONRequestBody(invoker)
158
159         var rspInvoker *invokerapi.PutOnboardedInvokersOnboardingIdResponse
160         rspInvoker, err = client.PutOnboardedInvokersOnboardingIdWithResponse(ctxHandler, onboardingId, putRegistrationsJSONRequestBody)
161
162         if err != nil {
163                 // Something really bad happened, tell Echo that our handler failed
164                 return err
165         }
166
167         if rspInvoker.StatusCode() != http.StatusOK {
168                 msg := string(rspInvoker.Body)
169                 return sendCoreError(ctx, rspInvoker.StatusCode(), msg)
170         }
171
172         rspAPIProviderEnrolmentDetails := *rspInvoker.JSON200
173         apiInvokerId := *rspAPIProviderEnrolmentDetails.ApiInvokerId
174
175         uri := ctx.Request().Host + ctx.Request().URL.String()
176         ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://`+path.Join(uri, apiInvokerId))
177         err = ctx.JSON(http.StatusOK, rspAPIProviderEnrolmentDetails)
178         if err != nil {
179                 // Something really bad happened, tell Echo that our handler failed
180                 return err
181         }
182
183         return nil
184 }
185
186 func (im *InvokerManager) ModifyIndApiInvokeEnrolment(ctx echo.Context, onboardingId string) error {
187         return ctx.NoContent(http.StatusNotImplemented)
188 }
189
190 // This function wraps sending of an error in the Error format, and
191 // handling the failure to marshal that.
192 func sendCoreError(ctx echo.Context, code int, message string) error {
193         pd := common29122.ProblemDetails{
194                 Cause:  &message,
195                 Status: &code,
196         }
197         err := ctx.JSON(code, pd)
198         return err
199 }