NONRTRIC-946: Add support for Kong routes
[nonrtric/plt/sme.git] / servicemanager / internal / providermanagement / providermanagement.go
1 // -
2 //   ========================LICENSE_START=================================
3 //   O-RAN-SC
4 //   %%
5 //   Copyright (C) 2023: 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 providermanagement
22
23 import (
24         "context"
25         "fmt"
26         "net/http"
27         "path"
28
29         echo "github.com/labstack/echo/v4"
30         log "github.com/sirupsen/logrus"
31
32         "oransc.org/nonrtric/servicemanager/internal/common29122"
33         provapi "oransc.org/nonrtric/servicemanager/internal/providermanagementapi"
34 )
35
36 type ProviderManager struct {
37         registeredProviders map[string]provapi.APIProviderEnrolmentDetails
38         CapifProtocol       string
39         CapifIPv4           common29122.Ipv4Addr
40         CapifPort           common29122.Port
41 }
42
43 func NewProviderManager(capifProtocol string, capifIPv4 common29122.Ipv4Addr, capifPort common29122.Port) *ProviderManager {
44         return &ProviderManager{
45                 registeredProviders: make(map[string]provapi.APIProviderEnrolmentDetails),
46                 CapifProtocol:       capifProtocol,
47                 CapifIPv4:           capifIPv4,
48                 CapifPort:           capifPort,
49         }
50 }
51
52 func (pm *ProviderManager) PostRegistrations(ctx echo.Context) error {
53         log.Trace("entering PostRegistrations")
54
55         newProvider, err := getProviderFromRequest(ctx)
56         if err != nil {
57                 errMsg := "Unable to register provider due to %s"
58                 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(errMsg, err))
59         }
60
61         capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-provider-management/v1/", pm.CapifProtocol, pm.CapifIPv4, pm.CapifPort)
62         client, err := provapi.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 := provapi.PostRegistrationsJSONRequestBody(newProvider)
75
76         var rspProvider *provapi.PostRegistrationsResponse
77         rspProvider, err = client.PostRegistrationsWithResponse(ctxHandler, postRegistrationsJSONRequestBody)
78
79         if (err != nil) || (rspProvider.StatusCode() != http.StatusCreated) {
80                 msg := string(rspProvider.Body)
81                 log.Errorf("error on PostRegistrationsWithResponse %s", msg)
82                 return sendCoreError(ctx, rspProvider.StatusCode(), msg)
83         }
84
85         rspAPIProviderEnrolmentDetails := *rspProvider.JSON201
86         apiProvDomId := *rspAPIProviderEnrolmentDetails.ApiProvDomId
87
88         uri := ctx.Request().Host + ctx.Request().URL.String()
89         ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://` + path.Join(uri, apiProvDomId))
90         if err := ctx.JSON(http.StatusCreated, rspAPIProviderEnrolmentDetails); err != nil {
91                 // Something really bad happened, tell Echo that our handler failed
92                 return err
93         }
94         return nil
95 }
96
97 func (pm *ProviderManager) DeleteRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
98         log.Tracef("entering DeleteRegistrationsRegistrationId registrationId %s", registrationId)
99
100         capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-provider-management/v1/", pm.CapifProtocol, pm.CapifIPv4, pm.CapifPort)
101         client, err := provapi.NewClientWithResponses(capifcoreUrl)
102         if err != nil {
103                 return err
104         }
105
106         var (
107                 ctxHandler context.Context
108                 cancel     context.CancelFunc
109         )
110         ctxHandler, cancel = context.WithCancel(context.Background())
111         defer cancel()
112
113         var rspProvider *provapi.DeleteRegistrationsRegistrationIdResponse
114         rspProvider, err = client.DeleteRegistrationsRegistrationIdWithResponse(ctxHandler, registrationId)
115
116         if (err != nil) || (rspProvider.StatusCode() != http.StatusNoContent) {
117                 msg := string(rspProvider.Body)
118                 log.Errorf("error on DeleteRegistrationsRegistrationIdWithResponse %s", msg)
119                 return sendCoreError(ctx, rspProvider.StatusCode(), msg)
120         }
121         return ctx.NoContent(http.StatusNoContent)
122 }
123
124 func (pm *ProviderManager) PutRegistrationsRegistrationId(ctx echo.Context, registrationId string) error {
125         log.Trace("entering PutRegistrationsRegistrationId")
126
127         updatedProvider, err := getProviderFromRequest(ctx)
128         if err != nil {
129                 msg := "Unable to register provider due to %s"
130                 log.Errorf("error on getProviderFromRequest %s", msg)
131                 return sendCoreError(ctx, http.StatusBadRequest, fmt.Sprintf(msg, err))
132         }
133
134         capifcoreUrl := fmt.Sprintf("%s://%s:%d/api-provider-management/v1/", pm.CapifProtocol, pm.CapifIPv4, pm.CapifPort)
135         client, err := provapi.NewClientWithResponses(capifcoreUrl)
136         if err != nil {
137                 return err
138         }
139
140         var (
141                 ctxHandler context.Context
142                 cancel     context.CancelFunc
143         )
144         ctxHandler, cancel = context.WithCancel(context.Background())
145         defer cancel()
146
147         putRegistrationsRegistrationIdJSONRequestBody := provapi.PutRegistrationsRegistrationIdJSONRequestBody(updatedProvider)
148
149         var rspProvider *provapi.PutRegistrationsRegistrationIdResponse
150         rspProvider, err = client.PutRegistrationsRegistrationIdWithResponse(ctxHandler, registrationId, putRegistrationsRegistrationIdJSONRequestBody)
151
152         if err != nil {
153                 msg := err.Error()
154                 log.Errorf("error on PutRegistrationsRegistrationIdWithResponse %s", msg)
155                 return sendCoreError(ctx, http.StatusInternalServerError, msg)
156         }
157
158         if rspProvider.StatusCode() != http.StatusOK {
159                 msg := string(rspProvider.Body)
160                 log.Errorf("error on PutRegistrationsRegistrationIdWithResponse %s", msg)
161                 return sendCoreError(ctx, rspProvider.StatusCode(), msg)
162         }
163
164         rspAPIProviderEnrolmentDetails := *rspProvider.JSON200
165         apiProvDomId := *rspAPIProviderEnrolmentDetails.ApiProvDomId
166
167         uri := ctx.Request().Host + ctx.Request().URL.String()
168         ctx.Response().Header().Set(echo.HeaderLocation, ctx.Scheme()+`://` + path.Join(uri, apiProvDomId))
169         if err := ctx.JSON(http.StatusOK, rspAPIProviderEnrolmentDetails); err != nil {
170                 // Something really bad happened, tell Echo that our handler failed
171                 return err
172         }
173         return nil
174 }
175
176 func (pm *ProviderManager) ModifyIndApiProviderEnrolment(ctx echo.Context, registrationId string) error {
177         return ctx.NoContent(http.StatusNotImplemented)
178 }
179
180 func getProviderFromRequest(ctx echo.Context) (provapi.APIProviderEnrolmentDetails, error) {
181         var updatedProvider provapi.APIProviderEnrolmentDetails
182         err := ctx.Bind(&updatedProvider)
183         if err != nil {
184                 return provapi.APIProviderEnrolmentDetails{}, fmt.Errorf("invalid format for provider")
185         }
186         return updatedProvider, nil
187 }
188
189 // This function wraps sending of an error in the Error format, and
190 // handling the failure to marshal that.
191 func sendCoreError(ctx echo.Context, code int, message string) error {
192         pd := common29122.ProblemDetails{
193                 Cause:  &message,
194                 Status: &code,
195         }
196         err := ctx.JSON(code, pd)
197         return err
198 }