3 ========================LICENSE_START=================================
6 Copyright (C) 2024 OpenInfra Foundation Europe. All rights reserved
8 Licensed under the Apache License, Version 2.0 (the "License");
9 you may not use this file except in compliance with the License.
10 You may obtain a copy of the License at
12 http://www.apache.org/licenses/LICENSE-2.0
14 Unless required by applicable law or agreed to in writing, software
15 distributed under the License is distributed on an "AS IS" BASIS,
16 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17 See the License for the specific language governing permissions and
18 limitations under the License.
19 ========================LICENSE_END===================================
23 # O-RAN-SC Non-RealTime RIC Service Manager
25 Service Manager is a Go implementation of a service that calls the CAPIF Core function. When publishing a service we create a Kong route and Kong service, https://konghq.com/. The InterfaceDescription that we return is updated to point to the Kong Data Plane. Therefore, the API interface that we return from Service Discovery has the Kong host and port, and not the original service's host and port. This allows the rApp's API call to be re-directed through Kong.
27 ## O-RAN-SC Non-RealTime RIC CAPIF Core Implementation
29 Service Manager is a Go implementation of the CAPIF Core function, which is based on the 3GPP "29.222 Common API Framework for 3GPP Northbound APIs (CAPIF)" interfaces, see https://portal.3gpp.org/desktopmodules/Specifications/SpecificationDetails.aspx?specificationId=3450.
31 See [CAPIF Core](../capifcore/README.md)
33 ## Generation of API Code
35 The CAPIF APIs are generated from the OpenAPI specifications provided by 3GPP. The `generate.sh` script downloads the
36 specifications from 3GPP, fixes them and then generates the APIs. While these files are checked into the repo, they can be re-generated using `generate.sh`.
42 The specifications are downloaded from the following site; https://www.3gpp.org/ftp/Specs/archive/29_series. To see
43 the APIs in swagger format, see the following link; https://github.com/jdegre/5GC_APIs/tree/Rel-17#common-api-framework-capif.
45 To fix the specifications there are three tools.
46 - `commoncollector`, collects type definitions from peripheral specifications to keep down the number of dependencies to
47 other specifications. The types to collect are listed in the `definitions.txt` file. Some fixes are hard-coded.
48 - `enumfixer`, fixes enumeration definitions so they can be properly generated.
49 - `specificationfixer`, fixes flaws in the specifications so they can be properly generated. All fixes are hard-coded.
53 First, we need to run `generate.sh` as described above to generate our API code from the 3GPP spec.
55 Before we can test or run Service Manager, we need to configure a .env file with the required parameters. Please see the template .env.example in the servicemanager directory.
57 You can set the environmental variable SERVICE_MANAGER_ENV to specify the .env file. For example, the following command specifies to use the config file
58 .env.development. If this flag is not set, first we try .env.development and then .env.
61 export SERVICE_MANAGER_ENV=development
64 ### CAPIFcore and Kong
66 We also need Kong and CAPIFcore to be running. Please see the examples in the `deploy` folder. You can also use https://gerrit.o-ran-sc.org/r/it/dep for deployment. Please see the notes at https://wiki.o-ran-sc.org/display/RICNR/Release+J%3A+Service+Manager
70 After generating the API code, we can build the application with the following command.
78 To run the unit tests for the application, first ensure that the .env file is configured. In the following example, we specify `.env.test`.
81 export SERVICE_MANAGER_ENV=test
87 To run as a local app, first ensure that the .env file is configured. In the following example, we specify `.env.development`.
90 export SERVICE_MANAGER_ENV=development
94 Service Manager is then available on the port configured in .env.
96 ## Building the Docker Image
98 The application can also be built as a Docker image, by using the following command. We build the image without a .env file. This is supplied by volume mounting at container run-time. Because we need to include CAPIFcore in the Docker build context, we build from the git repo's root directory, sme.
101 docker build -t servicemanager -f servicemanager/Dockerfile .
106 Please note that a special executable has been provided for deleting Kong routes and services that have been created by Service Manager in Kong. This executable is called `kongclearup` and is found in the working directory of the Service Manger Docker image, at `/app/servicemanager`. When we create a Kong route or service, we add Kong tags with information as follows.
113 When we delete Kong routes and services using `kongclearup`, we check for the existance of these tags, specifically, apfId, apiId and aefId. Only if these tags exist and have values do we proceed to delete the Kong service or route. The executable `kongclearup` uses the volume-mounted .env file to load the configuration giving the location of Kong. Please refer to `sme/servicemanager/internal/kongclearup.go`.
115 ## Stand-alone Deployment on Kubernetes
117 For a stand-alone deployment, please see the `deploy` folder for configurations to deploy to Service Manager to Kubernetes. We need the following steps.
118 - Deploy a PV for Kong's Postgres database (depends on your Kubernetes cluster, not needed for Minikube)
119 - Deploy a PVC for Kong's Postgres database
120 - Deploy Kong with Postgres
122 - Deploy Service Manager
124 We consolidate the above steps into the script `deploy-to-k8s.sh`. To delete the full deployment, you can use `delete-from-k8s.sh`. The deploy folder has the following structure.
132 We store the Kubernetes manifests files in the manifests in the subfolder. We store the shell scripts in the src folder.
134 In `deploy-to-k8s.sh`, we copy .env.example and use `sed` to replace the template values with values for running the Service Manager container. You will need to update this part of the script with your own values. There is an example sed replacement in function `substitute_manifest()` in `deploy-to-k8s.sh`. Here, you can substitute your own Docker images for CAPIFcore and Service Manager for local development.
136 In addition there are 2 switches that are added for developer convenience.
137 * --repo # allows you to specify your own docker repo, e.g. your Docker Hub id
138 * --env # allows you to specify an additional env file, and sets SERVICE_MANAGER_ENV in the Docker environment to point to this file.
140 The additional env file needs to exist in the sme/servicemanager folder so that kongclearup can access is. It is specified by its filename. The relative path ../.. is added in the `deploy-to-k8s.sh` script. For example, to use
142 `./deploy-to-k8s.sh --env .env.development`
144 ../../.env.development needs to exist.
148 A Postman collection has been included in this repo at sme/postman/ServiceManager.postman_collection.json.
150 ## Interface Descriptions
152 To distinguish between multiple interface descriptions, Service Manager prepends the port number and a hash code to the URL path.
154 ## Static and Dynamic Routes
156 We can specify either static or dynamic routes. Static routing defines a route when there is a single route for traffic to reach a destination. Dynamic routing allows us to specify path parameters. In this config file, we specify path parameters using regular expressions.
158 Kong uses the regex definition from the [Rust programming language](https://docs.rs/regex/latest/regex/) to specify the regular expression (regex) that describes the path parameters, [Kong regex](https://docs.konghq.com/gateway/latest/key-concepts/routes/#regular-expressions).
160 An example of a static path is as follows. This is the straightforward case.
166 An example of a dynamic path is
169 ~/rapps/(?<rappId>[a-zA-Z0-9]+([-_][a-zA-Z0-9]+)*)
172 Our dynamic path starts with a ~ character. In this example, we have a path parameter that is described by a regex capture group called rappId. The regex describes a word made of mixed-case alphanumeric characters optionally followed by one or more sets of a dash or underscore together with another word.
174 When the Service Manager client calls a dynamic API, we call the URL without the '~'. Kong substitutes the path parameter according to the rules specified in the regex. Therefore, we can call the above example by using
180 as the URL where my-rApp-id is the rApp id of in the rApp Manager. The name my-rApp-id has to match the regex shown above.
182 It is required to name the capture group in this YAML config file. The capture group name is used by Service Manager when creating a Kong Request Transformer plugin. We can specify multiple capture groups in a URL if there are multiple path parameters in the API path.
184 We create a Kong Request Transformer plugin with .data[].config.replace, as in the following example curl with abridged response.
187 curl -X GET http://oran-nonrtric-kong-admin.nonrtric.svc.cluster.local:8001/plugins
193 "uri": "/rapps/$(uri_captures[\"rappId\"])",
199 In our example, this allows Kong to match /rapps/my-rApp-id.
201 The Service Manager uses the following regex to search and replace the YAML file regexes.
204 /\(\?<([^>]+)>([^\/]+)/
207 Please note that the example path, /rapps/my-rApp-id, is not terminated by a '/'. Service Manager adds a '/' for internal matching. This made the regex easier to develop. Service Manager will match on /rapps/my-rApp-id/ for this case.