--- /dev/null
+[submodule "onap/oran"]
+ path = onap/oran
+ url = https://gerrit.onap.org/r/ccsdk/oran
API Functions
-------------
-See the following document for the Policy Agent API: nonrtric/policy-agent/docs/api.yaml
+See the following document for the Policy Agent API: nonrtric/onap/oran/docs/offeredapis/swagger/pms-api.yaml
SDNC A1 Controller
==================
* Maps O1 resources (ManagedElement) as defined in O1 to the controlling RIC.
| The Policy Agent can be accessed over the REST API or through the DMaaP Interface. The REST API is documented in the
-| *nonrtric/policy-agent/docs/api.yaml* file. Please refer to the README file of Policy Agent to know more about the API's.
+| *nonrtric/onap/oran/docs/offeredapis/swagger/pms-api.yaml* file. Please refer to the README file of Policy Agent to know more about the API's.
Configuration of certs
----------------------
--- /dev/null
+../../../onap/oran/docs/offeredapis/swagger/pms-api.json
\ No newline at end of file
.. http://creativecommons.org/licenses/by/4.0
.. Copyright (C) 2020 Nordix
-.. _sdnc-a1-controller-api:
-
.. |nbsp| unicode:: 0xA0
:trim:
.. |nbh| unicode:: 0x2011
:trim:
+.. _sdnc-a1-controller-api:
+
+
######################
SDNC A1 Controller API
######################
--- /dev/null
+Subproject commit e78c27efa1b2bbd9db762211e907777f49aba7d2
target
.checkstyle
policy-agent.iml
+config
ARG JAR
+EXPOSE 8081 8433
+
+
WORKDIR /opt/app/policy-agent
RUN mkdir -p /var/log/policy-agent
RUN mkdir -p /opt/app/policy-agent/etc/cert/
-
EXPOSE 8081 8433
ADD /config/application.yaml /opt/app/policy-agent/config/application.yaml
ADD /config/application_configuration.json /opt/app/policy-agent/data/application_configuration.json_example
-ADD target/${JAR} /opt/app/policy-agent/policy-agent.jar
ADD /config/keystore.jks /opt/app/policy-agent/etc/cert/keystore.jks
ADD /config/truststore.jks /opt/app/policy-agent/etc/cert/truststore.jks
-
RUN chmod -R 777 /opt/app/policy-agent/config/
+RUN chmod -R 777 /opt/app/policy-agent/data/
+ADD target/${JAR} /opt/app/policy-agent/policy-agent.jar
CMD ["java", "-jar", "/opt/app/policy-agent/policy-agent.jar"]
-
-
-
+++ /dev/null
-The keystore.jks and truststore.jks files are created by using the following commands (note that this is an example):
-
-1) Create a CA certificate and a private key:
-
-openssl genrsa -des3 -out CA-key.pem 2048
-openssl req -new -key CA-key.pem -x509 -days 1000 -out CA-cert.pem
-
-2) Create a keystore with a private key entry that is signed by the CA:
-
-keytool -genkeypair -alias policy_agent -keyalg RSA -keysize 2048 -keystore keystore.jks -validity 3650 -storepass policy_agent
-keytool -certreq -alias policy_agent -file request.csr -keystore keystore.jks -ext san=dns:your.domain.com -storepass policy_agent
-openssl x509 -req -days 365 -in request.csr -CA CA-cert.pem -CAkey CA-key.pem -CAcreateserial -out ca_signed-cert.pem
-keytool -importcert -alias ca_cert -file CA-cert.pem -keystore keystore.jks -trustcacerts -storepass policy_agent
-keytool -importcert -alias policy_agent -file ca_signed-cert.pem -keystore keystore.jks -trustcacerts -storepass policy_agent
-
-
-3) Create a trust store containing the CA cert (to trust all certs signed by the CA):
-
-keytool -genkeypair -alias not_used -keyalg RSA -keysize 2048 -keystore truststore.jks -validity 3650 -storepass policy_agent
-keytool -importcert -alias ca_cert -file CA-cert.pem -keystore truststore.jks -trustcacerts -storepass policy_agent
-
-
-4) Command for listing of the contents of jks files, examples:
-keytool -list -v -keystore keystore.jks -storepass policy_agent
-keytool -list -v -keystore truststore.jks -storepass policy_agent
-
-## License
-
-Copyright (C) 2020 Nordix Foundation. All rights reserved.
-Licensed under the Apache License, Version 2.0 (the "License");
-you may not use this file except in compliance with the License.
-You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing, software
-distributed under the License is distributed on an "AS IS" BASIS,
-WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-See the License for the specific language governing permissions and
-limitations under the License.
-
+++ /dev/null
-spring:
- profiles:
- active: prod
- main:
- allow-bean-definition-overriding: true
- aop:
- auto: false
-management:
- endpoints:
- web:
- exposure:
- include: "loggers,logfile,health,info,metrics,threaddump,heapdump"
-
-logging:
- level:
- ROOT: ERROR
- org.springframework: ERROR
- org.springframework.data: ERROR
- org.springframework.web.reactive.function.client.ExchangeFunctions: ERROR
- org.oransc.policyagent: INFO
- file:
- name: /var/log/policy-agent/application.log
-server:
- port : 8433
- http-port: 8081
- ssl:
- key-store-type: JKS
- key-store-password: policy_agent
- key-store: /opt/app/policy-agent/etc/cert/keystore.jks
- key-password: policy_agent
- key-alias: policy_agent
-app:
- filepath: /opt/app/policy-agent/data/application_configuration.json
- webclient:
- trust-store-used: false
- trust-store-password: policy_agent
- trust-store: /opt/app/policy-agent/etc/cert/truststore.jks
-
+++ /dev/null
-{
- "config": {
- "//description": "Application configuration",
- "controller": [
- {
- "name": "controller1",
- "baseUrl": "http://a1controller:8282",
- "userName": "admin",
- "password": "Kp8bJ4SXszM0WXlhak3eHlcse2gAw84vaoGGmJvUy2U"
- }
- ],
- "ric": [
- {
- "name": "ric1",
- "baseUrl": "http://ric1:8085/",
- "controller": "controller1",
- "managedElementIds": [
- "kista_1",
- "kista_2"
- ]
- }
- ]
- }
-}
\ No newline at end of file
+++ /dev/null
-swagger: '2.0'
-info:
- description: This page lists all the rest apis for the service.
- version: '1.0'
- title: A1 Policy management service
-host: 'localhost:8081'
-basePath: /
-tags:
- - name: A1 Policy Management
- description: Policy Controller
- - name: Health check
- description: Status Controller
- - name: RIC Repository
- description: Ric Repository Controller
- - name: Service registry and supervision
- description: Service Controller
-paths:
- /policies:
- get:
- tags:
- - A1 Policy Management
- summary: Query policies
- operationId: getPoliciesUsingGET
- produces:
- - '*/*'
- parameters:
- - name: ric
- in: query
- description: The name of the Near-RT RIC to get policies for.
- required: false
- type: string
- allowEmptyValue: false
- - name: service
- in: query
- description: The name of the service to get policies for.
- required: false
- type: string
- allowEmptyValue: false
- - name: type
- in: query
- description: The name of the policy type to get policies for.
- required: false
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: Policies
- schema:
- type: array
- items:
- $ref: '#/definitions/PolicyInfo'
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: RIC or type not found
- schema:
- type: string
- deprecated: false
- /policy:
- get:
- tags:
- - A1 Policy Management
- summary: Returns a policy configuration
- operationId: getPolicyUsingGET
- produces:
- - '*/*'
- parameters:
- - name: id
- in: query
- description: The ID of the policy instance.
- required: true
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: Policy found
- schema:
- type: object
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: Policy is not found
- deprecated: false
- put:
- tags:
- - A1 Policy Management
- summary: Put a policy
- operationId: putPolicyUsingPUT
- consumes:
- - application/json
- produces:
- - '*/*'
- parameters:
- - name: id
- in: query
- description: The ID of the policy instance.
- required: true
- type: string
- allowEmptyValue: false
- - in: body
- name: jsonBody
- description: jsonBody
- required: true
- schema:
- type: object
- - name: ric
- in: query
- description: The name of the Near-RT RIC where the policy will be created.
- required: true
- type: string
- allowEmptyValue: false
- - name: service
- in: query
- description: The name of the service creating the policy.
- required: true
- type: string
- allowEmptyValue: false
- - name: transient
- in: query
- description: If the policy is transient or not (boolean defaulted to false). A policy is transient if it will be forgotten when the service needs to reconnect to the Near-RT RIC.
- required: false
- type: boolean
- default: false
- allowEmptyValue: false
- x-example: false
- - name: type
- in: query
- description: The name of the policy type.
- required: false
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: Policy updated
- schema:
- type: object
- '201':
- description: Policy created
- schema:
- type: object
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: RIC or policy type is not found
- schema:
- type: string
- '423':
- description: RIC is not operational
- schema:
- type: string
- deprecated: false
- delete:
- tags:
- - A1 Policy Management
- summary: Delete a policy
- operationId: deletePolicyUsingDELETE
- produces:
- - '*/*'
- parameters:
- - name: id
- in: query
- description: The ID of the policy instance.
- required: true
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: OK
- schema:
- type: object
- '204':
- description: Policy deleted
- schema:
- type: object
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: Policy is not found
- schema:
- type: string
- '423':
- description: RIC is not operational
- schema:
- type: string
- deprecated: false
- /policy_ids:
- get:
- tags:
- - A1 Policy Management
- summary: 'Query policies, only IDs returned'
- operationId: getPolicyIdsUsingGET
- produces:
- - '*/*'
- parameters:
- - name: ric
- in: query
- description: The name of the Near-RT RIC to get policies for.
- required: false
- type: string
- allowEmptyValue: false
- - name: service
- in: query
- description: The name of the service to get policies for.
- required: false
- type: string
- allowEmptyValue: false
- - name: type
- in: query
- description: The name of the policy type to get policies for.
- required: false
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: Policy ids
- schema:
- type: array
- items:
- type: string
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: RIC or type not found
- schema:
- type: string
- deprecated: false
- /policy_schema:
- get:
- tags:
- - A1 Policy Management
- summary: Returns one policy type schema definition
- operationId: getPolicySchemaUsingGET
- produces:
- - '*/*'
- parameters:
- - name: id
- in: query
- description: The ID of the policy type to get the definition for.
- required: true
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: Policy schema
- schema:
- type: object
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: RIC is not found
- schema:
- type: string
- deprecated: false
- /policy_schemas:
- get:
- tags:
- - A1 Policy Management
- summary: Returns policy type schema definitions
- operationId: getPolicySchemasUsingGET
- produces:
- - '*/*'
- parameters:
- - name: ric
- in: query
- description: The name of the Near-RT RIC to get the definitions for.
- required: false
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: Policy schemas
- schema:
- type: array
- items:
- type: object
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: RIC is not found
- schema:
- type: string
- deprecated: false
- /policy_status:
- get:
- tags:
- - A1 Policy Management
- summary: Returns a policy status
- operationId: getPolicyStatusUsingGET
- produces:
- - '*/*'
- parameters:
- - name: id
- in: query
- description: The ID of the policy.
- required: true
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: Policy status
- schema:
- type: object
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: Policy is not found
- schema:
- type: string
- deprecated: false
- /policy_types:
- get:
- tags:
- - A1 Policy Management
- summary: Query policy type names
- operationId: getPolicyTypesUsingGET
- produces:
- - '*/*'
- parameters:
- - name: ric
- in: query
- description: The name of the Near-RT RIC to get types for.
- required: false
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: Policy type names
- schema:
- type: array
- items:
- type: string
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: RIC is not found
- schema:
- type: string
- deprecated: false
- /ric:
- get:
- tags:
- - RIC Repository
- summary: Returns the name of a RIC managing one Mananged Element
- operationId: getRicUsingGET
- produces:
- - '*/*'
- parameters:
- - name: managedElementId
- in: query
- description: The ID of the Managed Element
- required: true
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: RIC is found
- schema:
- type: string
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: RIC is not found
- schema:
- type: string
- deprecated: false
- /rics:
- get:
- tags:
- - RIC Repository
- summary: Query Near-RT RIC information
- operationId: getRicsUsingGET
- produces:
- - '*/*'
- parameters:
- - name: policyType
- in: query
- description: The name of the policy type
- required: false
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: OK
- schema:
- type: array
- items:
- $ref: '#/definitions/RicInfo'
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: Policy type is not found
- schema:
- type: string
- deprecated: false
- /service:
- put:
- tags:
- - Service registry and supervision
- summary: Register a service
- operationId: putServiceUsingPUT
- consumes:
- - application/json
- produces:
- - '*/*'
- parameters:
- - in: body
- name: registrationInfo
- description: registrationInfo
- required: true
- schema:
- $ref: '#/definitions/ServiceRegistrationInfo'
- responses:
- '200':
- description: Service updated
- schema:
- type: string
- '201':
- description: Service created
- schema:
- type: string
- '400':
- description: The ServiceRegistrationInfo is not accepted
- schema:
- type: string
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: Not Found
- deprecated: false
- /services:
- get:
- tags:
- - Service registry and supervision
- summary: Returns service information
- operationId: getServicesUsingGET
- produces:
- - '*/*'
- parameters:
- - name: name
- in: query
- description: The name of the service
- required: false
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: OK
- schema:
- type: array
- items:
- $ref: '#/definitions/ServiceStatus'
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: Service is not found
- schema:
- type: string
- deprecated: false
- delete:
- tags:
- - Service registry and supervision
- summary: Delete a service
- operationId: deleteServiceUsingDELETE
- produces:
- - '*/*'
- parameters:
- - name: name
- in: query
- description: The name of the service
- required: true
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: OK
- schema:
- type: string
- '204':
- description: OK
- schema:
- type: string
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: Service not found
- schema:
- type: string
- deprecated: false
- /services/keepalive:
- put:
- tags:
- - Service registry and supervision
- summary: Heartbeat from a serice
- operationId: keepAliveServiceUsingPUT
- consumes:
- - application/json
- produces:
- - '*/*'
- parameters:
- - name: name
- in: query
- description: The name of the service
- required: true
- type: string
- allowEmptyValue: false
- responses:
- '200':
- description: 'Service supervision timer refreshed, OK'
- schema:
- type: string
- '201':
- description: Created
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: 'The service is not found, needs re-registration'
- deprecated: false
- /status:
- get:
- tags:
- - Health check
- summary: Returns status and statistics of this service
- operationId: getStatusUsingGET
- produces:
- - '*/*'
- responses:
- '200':
- description: Service is living
- schema:
- type: string
- '401':
- description: Unauthorized
- '403':
- description: Forbidden
- '404':
- description: Not Found
- deprecated: false
-definitions:
- Mono«ResponseEntity«object»»:
- type: object
- title: Mono«ResponseEntity«object»»
- Mono«ResponseEntity«string»»:
- type: object
- title: Mono«ResponseEntity«string»»
- PolicyInfo:
- type: object
- properties:
- id:
- type: string
- description: identity of the policy
- json:
- type: object
- description: the configuration of the policy
- lastModified:
- type: string
- description: 'timestamp, last modification time'
- ric:
- type: string
- description: identity of the target Near-RT RIC
- service:
- type: string
- description: the name of the service owning the policy
- type:
- type: string
- description: name of the policy type
- title: PolicyInfo
- RicInfo:
- type: object
- properties:
- managedElementIds:
- type: array
- description: O1 identities for managed entities
- items:
- type: string
- policyTypes:
- type: array
- description: supported policy types
- items:
- type: string
- ricName:
- type: string
- description: identity of the ric
- state:
- type: string
- description: state info
- title: RicInfo
- ServiceRegistrationInfo:
- type: object
- required:
- - serviceName
- properties:
- callbackUrl:
- type: string
- description: callback for notifying of RIC synchronization
- keepAliveIntervalSeconds:
- type: integer
- format: int64
- description: 'keep alive interval for the service. This is a heartbeat supervision of the service, which in regular intevals must invoke a ''keepAlive'' REST call. When a service does not invoke this call within the given time, it is considered unavailble. An unavailable service will be automatically deregistered and its policies will be deleted. Value 0 means no timeout supervision.'
- serviceName:
- type: string
- description: identity of the service
- title: ServiceRegistrationInfo
- ServiceStatus:
- type: object
- properties:
- callbackUrl:
- type: string
- description: callback for notifying of RIC synchronization
- keepAliveIntervalSeconds:
- type: integer
- format: int64
- description: policy keep alive timeout
- serviceName:
- type: string
- description: identity of the service
- timeSinceLastActivitySeconds:
- type: integer
- format: int64
- description: time since last invocation by the service
- title: ServiceStatus
<artifactId>sonar-maven-plugin</artifactId>
<version>${sonar-maven-plugin.version}</version>
</plugin>
+ <plugin>
+ <groupId>org.codehaus.mojo</groupId>
+ <artifactId>exec-maven-plugin</artifactId>
+ <executions>
+ <execution>
+ <id>git submodule update</id>
+ <phase>initialize</phase>
+ <configuration>
+ <executable>git</executable>
+ <arguments>
+ <argument>submodule</argument>
+ <argument>update</argument>
+ <argument>--init</argument>
+ <argument>--recursive</argument>
+ </arguments>
+ </configuration>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>copy configuration</id>
+ <phase>initialize</phase>
+ <configuration>
+ <executable>cp</executable>
+ <arguments>
+ <argument>-r</argument>
+ <argument>../onap/oran/a1-policy-management/config</argument>
+ <argument>.</argument>
+ </arguments>
+ </configuration>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
</plugins>
</build>
<issueManagement>
<system>JIRA</system>
<url>https://jira.o-ran-sc.org/</url>
</issueManagement>
-</project>
+</project>
\ No newline at end of file
--- /dev/null
+../onap/oran/a1-policy-management/src
\ No newline at end of file
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent;
-
-import org.oransc.policyagent.dmaap.DmaapMessageConsumer;
-import org.oransc.policyagent.tasks.RefreshConfigTask;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.CommandLineRunner;
-import org.springframework.boot.SpringApplication;
-import org.springframework.boot.autoconfigure.SpringBootApplication;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-
-@SpringBootApplication
-public class Application {
-
- @Autowired
- private RefreshConfigTask configRefresh;
-
- @Autowired
- private DmaapMessageConsumer dmaapMessageConsumer;
-
- public static void main(String[] args) {
- SpringApplication.run(Application.class);
- }
-
- /**
- * Starts the configuration refresh task and reads the configuration.
- *
- * @param ctx the application context.
- *
- * @return the command line runner for the configuration refresh task.
- */
- @Bean
- public CommandLineRunner configRefreshRunner(ApplicationContext ctx) {
- return args -> configRefresh.start();
- }
-
- /**
- * Starts the DMaaP message consumer service.
- *
- * @param ctx the application context.
- *
- * @return the command line runner for the DMaaP message consumer service.
- */
- @Bean
- public CommandLineRunner dmaapMessageConsumerRunner(ApplicationContext ctx) {
- return args -> dmaapMessageConsumer.start();
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-
-import org.apache.catalina.connector.Connector;
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Rics;
-import org.oransc.policyagent.repository.Services;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
-import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-
-@Configuration
-class BeanFactory {
- private final ApplicationConfig applicationConfig = new ApplicationConfig();
-
- @Value("${server.http-port}")
- private int httpPort = 0;
-
- @Bean
- public Policies getPolicies() {
- return new Policies();
- }
-
- @Bean
- public PolicyTypes getPolicyTypes() {
- return new PolicyTypes();
- }
-
- @Bean
- public Rics getRics() {
- return new Rics();
- }
-
- @Bean
- public ApplicationConfig getApplicationConfig() {
- return this.applicationConfig;
- }
-
- @Bean
- Services getServices() {
- return new Services();
- }
-
- @Bean
- A1ClientFactory getA1ClientFactory() {
- return new A1ClientFactory(this.applicationConfig);
- }
-
- @Bean
- public ObjectMapper mapper() {
- return new ObjectMapper();
- }
-
- @Bean
- public ServletWebServerFactory servletContainer() {
- TomcatServletWebServerFactory tomcat = new TomcatServletWebServerFactory();
- if (httpPort > 0) {
- tomcat.addAdditionalTomcatConnectors(getHttpConnector(httpPort));
- }
- return tomcat;
- }
-
- private static Connector getHttpConnector(int httpPort) {
- Connector connector = new Connector(TomcatServletWebServerFactory.DEFAULT_PROTOCOL);
- connector.setScheme("http");
- connector.setPort(httpPort);
- connector.setSecure(false);
- return connector;
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent;
-
-import com.google.common.base.Predicates;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
-import org.springframework.web.servlet.config.annotation.WebMvcConfigurationSupport;
-
-import springfox.documentation.builders.ApiInfoBuilder;
-import springfox.documentation.builders.PathSelectors;
-import springfox.documentation.builders.RequestHandlerSelectors;
-import springfox.documentation.service.ApiInfo;
-import springfox.documentation.spi.DocumentationType;
-import springfox.documentation.spring.web.plugins.Docket;
-import springfox.documentation.swagger2.annotations.EnableSwagger2;
-
-/**
- * Swagger configuration class that uses swagger2 documentation type and scans
- * all the controllers under org.oransc.policyagent.controllers package. To
- * access the swagger gui go to http://ip:port/swagger-ui.html
- *
- */
-@Configuration
-@EnableSwagger2
-public class SwaggerConfig extends WebMvcConfigurationSupport {
-
- static final String API_TITLE = "A1 Policy management service";
- static final String DESCRIPTION = "This page lists all the rest apis for the service.";
- static final String VERSION = "1.0";
- @SuppressWarnings("squid:S1075") // Refactor your code to get this URI from a customizable parameter.
- static final String RESOURCES_PATH = "classpath:/META-INF/resources/";
- static final String WEBJARS_PATH = RESOURCES_PATH + "webjars/";
- static final String SWAGGER_UI = "swagger-ui.html";
- static final String WEBJARS = "/webjars/**";
-
- /**
- * Gets the API info.
- *
- * @return the API info.
- */
- @Bean
- public Docket api() {
- return new Docket(DocumentationType.SWAGGER_2) //
- .apiInfo(apiInfo()) //
- .select() //
- .apis(RequestHandlerSelectors.any()) //
- .paths(PathSelectors.any()) //
- .paths(Predicates.not(PathSelectors.regex("/error"))) //
- // this endpoint is not implemented, but was visible for Swagger
- .paths(Predicates.not(PathSelectors.regex("/actuator.*"))) //
- // this endpoint is implemented by spring framework, exclude for now
- .build();
- }
-
- private static ApiInfo apiInfo() {
- return new ApiInfoBuilder() //
- .title(API_TITLE) //
- .description(DESCRIPTION) //
- .version(VERSION) //
- .build();
- }
-
- @Override
- protected void addResourceHandlers(ResourceHandlerRegistry registry) {
- registry.addResourceHandler(SWAGGER_UI) //
- .addResourceLocations(RESOURCES_PATH);
-
- registry.addResourceHandler(WEBJARS) //
- .addResourceLocations(WEBJARS_PATH);
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.aspect;
-
-import org.aspectj.lang.JoinPoint;
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.annotation.After;
-import org.aspectj.lang.annotation.Around;
-import org.aspectj.lang.annotation.Aspect;
-import org.aspectj.lang.annotation.Before;
-import org.aspectj.lang.reflect.MethodSignature;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.stereotype.Component;
-import org.springframework.util.StopWatch;
-
-@Aspect
-@Component
-public class LogAspect {
-
- private static final Logger logger = LoggerFactory.getLogger(LogAspect.class);
-
- @Around("execution(* org.oransc.policyagent..*(..)))")
- public void executimeTime(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
- final StopWatch stopWatch = new StopWatch();
- stopWatch.start();
- proceedingJoinPoint.proceed();
- stopWatch.stop();
- MethodSignature methodSignature = (MethodSignature) proceedingJoinPoint.getSignature();
- String className = methodSignature.getDeclaringType().getSimpleName();
- String methodName = methodSignature.getName();
- logger.trace("Execution time of {}.{}: {} ms", className, methodName, stopWatch.getTotalTimeMillis());
- }
-
- @Before("execution(* org.oransc.policyagent..*(..)))")
- public void entryLog(final JoinPoint joinPoint) {
- logger.trace("Entering method: {}", joinPoint.getSignature().getName());
- }
-
- @After("execution(* org.oransc.policyagent..*(..)))")
- public void exitLog(final JoinPoint joinPoint) {
- logger.trace("Exiting method: {}", joinPoint.getSignature().getName());
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import java.util.List;
-
-import org.oransc.policyagent.repository.Policy;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-/**
- * Common interface for 'A1' Policy access. Implementations of this interface
- * adapts to the different southbound REST APIs supported.
- */
-public interface A1Client {
-
- public enum A1ProtocolType {
- UNKNOWN, //
- STD_V1_1, // STD A1 version 1.1
- OSC_V1, // OSC 'A1'
- SDNC_OSC_STD_V1_1, // SDNC_OSC with STD A1 version 1.1 southbound
- SDNC_OSC_OSC_V1, // SDNC_OSC with OSC 'A1' southbound
- SDNC_ONAP
- }
-
- public Mono<A1ProtocolType> getProtocolVersion();
-
- public Mono<List<String>> getPolicyTypeIdentities();
-
- public Mono<List<String>> getPolicyIdentities();
-
- public Mono<String> getPolicyTypeSchema(String policyTypeId);
-
- public Mono<String> putPolicy(Policy policy);
-
- public Mono<String> deletePolicy(Policy policy);
-
- public Flux<String> deleteAllPolicies();
-
- public Mono<String> getPolicyStatus(Policy policy);
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import lombok.Getter;
-
-import org.oransc.policyagent.clients.A1Client.A1ProtocolType;
-import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.configuration.ControllerConfig;
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.oransc.policyagent.repository.Ric;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import reactor.core.publisher.Mono;
-
-/**
- * Factory for A1 clients that supports four different protocol versions of the
- * A1 api.
- */
-public class A1ClientFactory {
-
- private static final Logger logger = LoggerFactory.getLogger(A1ClientFactory.class);
-
- @Getter
- private final ApplicationConfig appConfig;
-
- @Autowired
- public A1ClientFactory(ApplicationConfig appConfig) {
- this.appConfig = appConfig;
- }
-
- /**
- * Creates an A1 client with the correct A1 protocol for the provided Ric.
- *
- * <p>
- * It detects the protocol version by trial and error, since there is no
- * getVersion method specified in the A1 api yet.
- *
- * <p>
- * As a side effect it also sets the protocol version in the provided Ric. This
- * means that after the first successful creation it won't have to try which
- * protocol to use, but can create the client directly.
- *
- * @param ric The RIC to get a client for.
- * @return a client with the correct protocol, or a ServiceException if none of
- * the protocols are supported by the Ric.
- */
- public Mono<A1Client> createA1Client(Ric ric) {
- return getProtocolVersion(ric) //
- .flatMap(version -> createA1ClientMono(ric, version));
- }
-
- A1Client createClient(Ric ric, A1ProtocolType version) throws ServiceException {
- if (version == A1ProtocolType.STD_V1_1) {
- assertNoControllerConfig(ric, version);
- return new StdA1ClientVersion1(ric.getConfig(), this.appConfig.getWebClientConfig());
- } else if (version == A1ProtocolType.OSC_V1) {
- assertNoControllerConfig(ric, version);
- return new OscA1Client(ric.getConfig(), this.appConfig.getWebClientConfig());
- } else if (version == A1ProtocolType.SDNC_OSC_STD_V1_1 || version == A1ProtocolType.SDNC_OSC_OSC_V1) {
- return new SdncOscA1Client(version, ric.getConfig(), getControllerConfig(ric),
- this.appConfig.getWebClientConfig());
- } else if (version == A1ProtocolType.SDNC_ONAP) {
- return new SdncOnapA1Client(ric.getConfig(), getControllerConfig(ric), this.appConfig.getWebClientConfig());
- } else {
- logger.error("Unhandled protocol: {}", version);
- throw new ServiceException("Unhandled protocol");
- }
- }
-
- private ControllerConfig getControllerConfig(Ric ric) throws ServiceException {
- String controllerName = ric.getConfig().controllerName();
- if (controllerName.isEmpty()) {
- ric.setProtocolVersion(A1ProtocolType.UNKNOWN);
- throw new ServiceException("No controller configured for RIC: " + ric.name());
- }
- try {
- return this.appConfig.getControllerConfig(controllerName);
- } catch (ServiceException e) {
- ric.setProtocolVersion(A1ProtocolType.UNKNOWN);
- throw e;
- }
- }
-
- private void assertNoControllerConfig(Ric ric, A1ProtocolType version) throws ServiceException {
- if (!ric.getConfig().controllerName().isEmpty()) {
- ric.setProtocolVersion(A1ProtocolType.UNKNOWN);
- throw new ServiceException(
- "Controller config should be empty, ric: " + ric.name() + " when using protocol version: " + version);
- }
- }
-
- private Mono<A1Client> createA1ClientMono(Ric ric, A1ProtocolType version) {
- try {
- return Mono.just(createClient(ric, version));
- } catch (ServiceException e) {
- return Mono.error(e);
- }
- }
-
- private Mono<A1Client.A1ProtocolType> getProtocolVersion(Ric ric) {
- if (ric.getProtocolVersion() == A1ProtocolType.UNKNOWN) {
- return fetchVersion(ric, A1ProtocolType.STD_V1_1) //
- .onErrorResume(notUsed -> fetchVersion(ric, A1ProtocolType.OSC_V1)) //
- .onErrorResume(notUsed -> fetchVersion(ric, A1ProtocolType.SDNC_OSC_STD_V1_1)) //
- .onErrorResume(notUsed -> fetchVersion(ric, A1ProtocolType.SDNC_ONAP)) //
- .doOnNext(ric::setProtocolVersion)
- .doOnNext(version -> logger.debug("Established protocol version:{} for Ric: {}", version, ric.name())) //
- .doOnError(notUsed -> logger.warn("Could not get protocol version from RIC: {}", ric.name())) //
- .onErrorResume(
- notUsed -> Mono.error(new ServiceException("Protocol negotiation failed for " + ric.name())));
- } else {
- return Mono.just(ric.getProtocolVersion());
- }
- }
-
- private Mono<A1ProtocolType> fetchVersion(Ric ric, A1ProtocolType protocolType) {
- return createA1ClientMono(ric, protocolType) //
- .flatMap(A1Client::getProtocolVersion);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-/**
- * Builder for A1 influenced REST APIs
- */
-interface A1UriBuilder {
- String createPutPolicyUri(String type, String policyId);
-
- String createDeleteUri(String type, String policyId);
-
- String createGetPolicyStatusUri(String type, String policyId);
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import io.netty.channel.ChannelOption;
-import io.netty.handler.ssl.SslContext;
-import io.netty.handler.ssl.SslContextBuilder;
-import io.netty.handler.ssl.util.InsecureTrustManagerFactory;
-import io.netty.handler.timeout.ReadTimeoutHandler;
-import io.netty.handler.timeout.WriteTimeoutHandler;
-
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.lang.invoke.MethodHandles;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.Certificate;
-import java.security.cert.CertificateException;
-import java.security.cert.X509Certificate;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Collectors;
-
-import javax.net.ssl.KeyManagerFactory;
-
-import org.oransc.policyagent.configuration.WebClientConfig;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.MediaType;
-import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.reactive.ReactorClientHttpConnector;
-import org.springframework.lang.Nullable;
-import org.springframework.util.ResourceUtils;
-import org.springframework.web.reactive.function.client.ExchangeStrategies;
-import org.springframework.web.reactive.function.client.WebClient;
-import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-
-import reactor.core.publisher.Mono;
-import reactor.netty.http.client.HttpClient;
-import reactor.netty.resources.ConnectionProvider;
-import reactor.netty.tcp.TcpClient;
-
-/**
- * Generic reactive REST client.
- */
-public class AsyncRestClient {
- private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private WebClient webClient = null;
- private final String baseUrl;
- private static final AtomicInteger sequenceNumber = new AtomicInteger();
- private final WebClientConfig clientConfig;
- static KeyStore clientTrustStore = null;
- private boolean sslEnabled = true;
-
- public AsyncRestClient(String baseUrl) {
- this(baseUrl, null);
- this.sslEnabled = false;
- }
-
- public AsyncRestClient(String baseUrl, WebClientConfig config) {
- this.baseUrl = baseUrl;
- this.clientConfig = config;
- }
-
- public Mono<ResponseEntity<String>> postForEntity(String uri, @Nullable String body) {
- Object traceTag = createTraceTag();
- logger.debug("{} POST uri = '{}{}''", traceTag, baseUrl, uri);
- logger.trace("{} POST body: {}", traceTag, body);
- Mono<String> bodyProducer = body != null ? Mono.just(body) : Mono.empty();
- return getWebClient() //
- .flatMap(client -> {
- RequestHeadersSpec<?> request = client.post() //
- .uri(uri) //
- .contentType(MediaType.APPLICATION_JSON) //
- .body(bodyProducer, String.class);
- return retrieve(traceTag, request);
- });
- }
-
- public Mono<String> post(String uri, @Nullable String body) {
- return postForEntity(uri, body) //
- .flatMap(this::toBody);
- }
-
- public Mono<String> postWithAuthHeader(String uri, String body, String username, String password) {
- Object traceTag = createTraceTag();
- logger.debug("{} POST (auth) uri = '{}{}''", traceTag, baseUrl, uri);
- logger.trace("{} POST body: {}", traceTag, body);
- return getWebClient() //
- .flatMap(client -> {
- RequestHeadersSpec<?> request = client.post() //
- .uri(uri) //
- .headers(headers -> headers.setBasicAuth(username, password)) //
- .contentType(MediaType.APPLICATION_JSON) //
- .bodyValue(body);
- return retrieve(traceTag, request) //
- .flatMap(this::toBody);
- });
- }
-
- public Mono<ResponseEntity<String>> putForEntity(String uri, String body) {
- Object traceTag = createTraceTag();
- logger.debug("{} PUT uri = '{}{}''", traceTag, baseUrl, uri);
- logger.trace("{} PUT body: {}", traceTag, body);
- return getWebClient() //
- .flatMap(client -> {
- RequestHeadersSpec<?> request = client.put() //
- .uri(uri) //
- .contentType(MediaType.APPLICATION_JSON) //
- .bodyValue(body);
- return retrieve(traceTag, request);
- });
- }
-
- public Mono<ResponseEntity<String>> putForEntity(String uri) {
- Object traceTag = createTraceTag();
- logger.debug("{} PUT uri = '{}{}''", traceTag, baseUrl, uri);
- logger.trace("{} PUT body: <empty>", traceTag);
- return getWebClient() //
- .flatMap(client -> {
- RequestHeadersSpec<?> request = client.put() //
- .uri(uri);
- return retrieve(traceTag, request);
- });
- }
-
- public Mono<String> put(String uri, String body) {
- return putForEntity(uri, body) //
- .flatMap(this::toBody);
- }
-
- public Mono<ResponseEntity<String>> getForEntity(String uri) {
- Object traceTag = createTraceTag();
- logger.debug("{} GET uri = '{}{}''", traceTag, baseUrl, uri);
- return getWebClient() //
- .flatMap(client -> {
- RequestHeadersSpec<?> request = client.get().uri(uri);
- return retrieve(traceTag, request);
- });
- }
-
- public Mono<String> get(String uri) {
- return getForEntity(uri) //
- .flatMap(this::toBody);
- }
-
- public Mono<ResponseEntity<String>> deleteForEntity(String uri) {
- Object traceTag = createTraceTag();
- logger.debug("{} DELETE uri = '{}{}''", traceTag, baseUrl, uri);
- return getWebClient() //
- .flatMap(client -> {
- RequestHeadersSpec<?> request = client.delete().uri(uri);
- return retrieve(traceTag, request);
- });
- }
-
- public Mono<String> delete(String uri) {
- return deleteForEntity(uri) //
- .flatMap(this::toBody);
- }
-
- private Mono<ResponseEntity<String>> retrieve(Object traceTag, RequestHeadersSpec<?> request) {
- final Class<String> clazz = String.class;
- return request.retrieve() //
- .toEntity(clazz) //
- .doOnNext(entity -> logger.trace("{} Received: {}", traceTag, entity.getBody())) //
- .doOnError(throwable -> onHttpError(traceTag, throwable));
- }
-
- private static Object createTraceTag() {
- return sequenceNumber.incrementAndGet();
- }
-
- private void onHttpError(Object traceTag, Throwable t) {
- if (t instanceof WebClientResponseException) {
- WebClientResponseException exception = (WebClientResponseException) t;
- logger.debug("{} HTTP error status = '{}', body '{}'", traceTag, exception.getStatusCode(),
- exception.getResponseBodyAsString());
- } else {
- logger.debug("{} HTTP error", traceTag, t);
- }
- }
-
- private Mono<String> toBody(ResponseEntity<String> entity) {
- if (entity.getBody() == null) {
- return Mono.just("");
- } else {
- return Mono.just(entity.getBody());
- }
- }
-
- private boolean isCertificateEntry(KeyStore trustStore, String alias) {
- try {
- return trustStore.isCertificateEntry(alias);
- } catch (KeyStoreException e) {
- logger.error("Error reading truststore {}", e.getMessage());
- return false;
- }
- }
-
- private Certificate getCertificate(KeyStore trustStore, String alias) {
- try {
- return trustStore.getCertificate(alias);
- } catch (KeyStoreException e) {
- logger.error("Error reading truststore {}", e.getMessage());
- return null;
- }
- }
-
- private static synchronized KeyStore getTrustStore(String trustStorePath, String trustStorePass)
- throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
- if (clientTrustStore == null) {
- KeyStore store = KeyStore.getInstance(KeyStore.getDefaultType());
- store.load(new FileInputStream(ResourceUtils.getFile(trustStorePath)), trustStorePass.toCharArray());
- clientTrustStore = store;
- }
- return clientTrustStore;
- }
-
- private SslContext createSslContextRejectingUntrustedPeers(String trustStorePath, String trustStorePass,
- KeyManagerFactory keyManager)
- throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException {
-
- final KeyStore trustStore = getTrustStore(trustStorePath, trustStorePass);
- List<Certificate> certificateList = Collections.list(trustStore.aliases()).stream() //
- .filter(alias -> isCertificateEntry(trustStore, alias)) //
- .map(alias -> getCertificate(trustStore, alias)) //
- .collect(Collectors.toList());
- final X509Certificate[] certificates = certificateList.toArray(new X509Certificate[certificateList.size()]);
-
- return SslContextBuilder.forClient() //
- .keyManager(keyManager) //
- .trustManager(certificates) //
- .build();
- }
-
- private SslContext createSslContext(KeyManagerFactory keyManager)
- throws NoSuchAlgorithmException, CertificateException, KeyStoreException, IOException {
- if (this.clientConfig.isTrustStoreUsed()) {
- return createSslContextRejectingUntrustedPeers(this.clientConfig.trustStore(),
- this.clientConfig.trustStorePassword(), keyManager);
- } else {
- // Trust anyone
- return SslContextBuilder.forClient() //
- .keyManager(keyManager) //
- .trustManager(InsecureTrustManagerFactory.INSTANCE) //
- .build();
- }
- }
-
- private TcpClient createTcpClientSecure(SslContext sslContext) {
- return TcpClient.create(ConnectionProvider.newConnection()) //
- .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) //
- .secure(c -> c.sslContext(sslContext)) //
- .doOnConnected(connection -> {
- connection.addHandlerLast(new ReadTimeoutHandler(30));
- connection.addHandlerLast(new WriteTimeoutHandler(30));
- });
- }
-
- private TcpClient createTcpClientInsecure() {
- return TcpClient.create(ConnectionProvider.newConnection()) //
- .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 10_000) //
- .doOnConnected(connection -> {
- connection.addHandlerLast(new ReadTimeoutHandler(30));
- connection.addHandlerLast(new WriteTimeoutHandler(30));
- });
- }
-
- private WebClient createWebClient(String baseUrl, TcpClient tcpClient) {
- HttpClient httpClient = HttpClient.from(tcpClient);
- ReactorClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
- ExchangeStrategies exchangeStrategies = ExchangeStrategies.builder() //
- .codecs(configurer -> configurer.defaultCodecs().maxInMemorySize(-1)) //
- .build();
- return WebClient.builder() //
- .clientConnector(connector) //
- .baseUrl(baseUrl) //
- .exchangeStrategies(exchangeStrategies) //
- .build();
- }
-
- private Mono<WebClient> getWebClient() {
- if (this.webClient == null) {
- try {
- if (this.sslEnabled) {
- final KeyManagerFactory keyManager =
- KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
- final KeyStore keyStore = KeyStore.getInstance(this.clientConfig.keyStoreType());
- final String keyStoreFile = this.clientConfig.keyStore();
- final String keyStorePassword = this.clientConfig.keyStorePassword();
- final String keyPassword = this.clientConfig.keyPassword();
- try (final InputStream inputStream = new FileInputStream(keyStoreFile)) {
- keyStore.load(inputStream, keyStorePassword.toCharArray());
- }
- keyManager.init(keyStore, keyPassword.toCharArray());
- SslContext sslContext = createSslContext(keyManager);
- TcpClient tcpClient = createTcpClientSecure(sslContext);
- this.webClient = createWebClient(this.baseUrl, tcpClient);
- } else {
- TcpClient tcpClient = createTcpClientInsecure();
- this.webClient = createWebClient(this.baseUrl, tcpClient);
- }
- } catch (Exception e) {
- logger.error("Could not create WebClient {}", e.getMessage());
- return Mono.error(e);
- }
- }
- return Mono.just(this.webClient);
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import java.lang.invoke.MethodHandles;
-import java.util.List;
-
-import org.json.JSONObject;
-import org.oransc.policyagent.configuration.RicConfig;
-import org.oransc.policyagent.configuration.WebClientConfig;
-import org.oransc.policyagent.repository.Policy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-/**
- * Client for accessing OSC A1 REST API
- */
-@SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally
-public class OscA1Client implements A1Client {
- static final int CONCURRENCY_RIC = 1; // How may paralell requests that is sent to one NearRT RIC
-
- public static class UriBuilder implements A1UriBuilder {
- private final RicConfig ricConfig;
-
- public UriBuilder(RicConfig ricConfig) {
- this.ricConfig = ricConfig;
- }
-
- @Override
- public String createPutPolicyUri(String type, String policyId) {
- return createPolicyUri(type, policyId);
- }
-
- /**
- * /a1-p/policytypes/{policy_type_id}/policies
- */
- public String createGetPolicyIdsUri(String type) {
- return createPolicyTypeUri(type) + "/policies";
- }
-
- @Override
- public String createDeleteUri(String type, String policyId) {
- return createPolicyUri(type, policyId);
- }
-
- /**
- * ​/a1-p​/policytypes​/{policy_type_id}​/policies​/{policy_instance_id}​/status
- */
- @Override
- public String createGetPolicyStatusUri(String type, String policyId) {
- return createPolicyUri(type, policyId) + "/status";
- }
-
- /**
- * ​/a1-p​/healthcheck
- */
- public String createHealtcheckUri() {
- return baseUri() + "/healthcheck";
- }
-
- /**
- * /a1-p/policytypes/{policy_type_id}
- */
- public String createGetSchemaUri(String type) {
- return this.createPolicyTypeUri(type);
- }
-
- /**
- * ​/a1-p​/policytypes​/{policy_type_id}
- */
- public String createPolicyTypesUri() {
- return baseUri() + "/policytypes";
- }
-
- /**
- * ​/a1-p​/policytypes​/{policy_type_id}​/policies​/{policy_instance_id}
- */
- private String createPolicyUri(String type, String id) {
- return createPolicyTypeUri(type) + "/policies/" + id;
- }
-
- /**
- * /a1-p/policytypes/{policy_type_id}
- */
- private String createPolicyTypeUri(String type) {
- return createPolicyTypesUri() + "/" + type;
- }
-
- private String baseUri() {
- return ricConfig.baseUrl() + "/a1-p";
- }
- }
-
- private static final String TITLE = "title";
- private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private final AsyncRestClient restClient;
- private final UriBuilder uri;
-
- public OscA1Client(RicConfig ricConfig, WebClientConfig clientConfig) {
- this(ricConfig, new AsyncRestClient("", clientConfig));
- }
-
- public OscA1Client(RicConfig ricConfig, AsyncRestClient restClient) {
- this.restClient = restClient;
- logger.debug("OscA1Client for ric: {}", ricConfig.name());
-
- uri = new UriBuilder(ricConfig);
- }
-
- public static Mono<String> extractCreateSchema(String policyTypeResponse, String policyTypeId) {
- try {
- JSONObject obj = new JSONObject(policyTypeResponse);
- JSONObject schemaObj = obj.getJSONObject("create_schema");
- schemaObj.put(TITLE, policyTypeId);
- return Mono.just(schemaObj.toString());
- } catch (Exception e) {
- String exceptionString = e.toString();
- logger.error("Unexpected response for policy type: {}, exception: {}", policyTypeResponse, exceptionString);
- return Mono.error(e);
- }
- }
-
- @Override
- public Mono<List<String>> getPolicyTypeIdentities() {
- return getPolicyTypeIds() //
- .collectList();
- }
-
- @Override
- public Mono<List<String>> getPolicyIdentities() {
- return getPolicyTypeIds() //
- .flatMap(this::getPolicyIdentitiesByType) //
- .collectList();
- }
-
- @Override
- public Mono<String> getPolicyTypeSchema(String policyTypeId) {
- String schemaUri = uri.createGetSchemaUri(policyTypeId);
- return restClient.get(schemaUri) //
- .flatMap(response -> extractCreateSchema(response, policyTypeId));
- }
-
- @Override
- public Mono<String> putPolicy(Policy policy) {
- String policyUri = this.uri.createPutPolicyUri(policy.type().name(), policy.id());
- return restClient.put(policyUri, policy.json());
- }
-
- @Override
- public Mono<String> deletePolicy(Policy policy) {
- return deletePolicyById(policy.type().name(), policy.id());
- }
-
- @Override
- public Mono<A1ProtocolType> getProtocolVersion() {
- return restClient.get(uri.createHealtcheckUri()) //
- .flatMap(notUsed -> Mono.just(A1ProtocolType.OSC_V1));
- }
-
- @Override
- public Flux<String> deleteAllPolicies() {
- return getPolicyTypeIds() //
- .flatMap(this::deletePoliciesForType, CONCURRENCY_RIC);
- }
-
- @Override
- public Mono<String> getPolicyStatus(Policy policy) {
- String statusUri = uri.createGetPolicyStatusUri(policy.type().name(), policy.id());
- return restClient.get(statusUri);
-
- }
-
- private Flux<String> getPolicyTypeIds() {
- return restClient.get(uri.createPolicyTypesUri()) //
- .flatMapMany(SdncJsonHelper::parseJsonArrayOfString);
- }
-
- private Flux<String> getPolicyIdentitiesByType(String typeId) {
- return restClient.get(uri.createGetPolicyIdsUri(typeId)) //
- .flatMapMany(SdncJsonHelper::parseJsonArrayOfString);
- }
-
- private Mono<String> deletePolicyById(String typeId, String policyId) {
- String policyUri = uri.createDeleteUri(typeId, policyId);
- return restClient.delete(policyUri);
- }
-
- private Flux<String> deletePoliciesForType(String typeId) {
- return getPolicyIdentitiesByType(typeId) //
- .flatMap(policyId -> deletePolicyById(typeId, policyId), CONCURRENCY_RIC);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import com.google.gson.FieldNamingPolicy;
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-/**
- * Common json functionality used by the SDNC clients
- */
-@SuppressWarnings("java:S1192") // Same text in several traces
-class SdncJsonHelper {
- private static Gson gson = new GsonBuilder() //
- .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) //
- .create();
- private static final String OUTPUT = "output";
- private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- private SdncJsonHelper() {
- }
-
- public static Flux<String> parseJsonArrayOfString(String inputString) {
- try {
- List<String> arrayList = new ArrayList<>();
- if (!inputString.isEmpty()) {
- JSONArray jsonArray = new JSONArray(inputString);
- for (int i = 0; i < jsonArray.length(); i++) {
- Object value = jsonArray.get(i);
- arrayList.add(value.toString());
- }
- }
- return Flux.fromIterable(arrayList);
- } catch (JSONException ex) { // invalid json
- logger.debug("Invalid json {}", ex.getMessage());
- return Flux.error(ex);
- }
- }
-
- public static <T> String createInputJsonString(T params) {
- JsonElement paramsJson = gson.toJsonTree(params);
- JsonObject jsonObj = new JsonObject();
- jsonObj.add("input", paramsJson);
- return gson.toJson(jsonObj);
- }
-
- public static <T> String createOutputJsonString(T params) {
- JsonElement paramsJson = gson.toJsonTree(params);
- JsonObject jsonObj = new JsonObject();
- jsonObj.add(OUTPUT, paramsJson);
- return gson.toJson(jsonObj);
- }
-
- public static Mono<JSONObject> getOutput(String response) {
- try {
- JSONObject outputJson = new JSONObject(response);
- JSONObject responseParams = outputJson.getJSONObject(OUTPUT);
- return Mono.just(responseParams);
- } catch (JSONException ex) { // invalid json
- logger.debug("Invalid json {}", ex.getMessage());
- return Mono.error(ex);
- }
- }
-
- public static Mono<String> getValueFromResponse(String response, String key) {
- return getOutput(response) //
- .flatMap(responseParams -> {
- if (!responseParams.has(key)) {
- return Mono.just("");
- }
- String value = responseParams.get(key).toString();
- return Mono.just(value);
- });
- }
-
- public static Mono<String> extractPolicySchema(String inputString) {
- try {
- JSONObject jsonObject = new JSONObject(inputString);
- JSONObject schemaObject = jsonObject.getJSONObject("policySchema");
- String schemaString = schemaObject.toString();
- return Mono.just(schemaString);
- } catch (JSONException ex) { // invalid json
- logger.debug("Invalid json {}", ex.getMessage());
- return Mono.error(ex);
- }
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-
-import org.immutables.gson.Gson;
-import org.immutables.value.Value;
-import org.oransc.policyagent.configuration.ControllerConfig;
-import org.oransc.policyagent.configuration.RicConfig;
-import org.oransc.policyagent.configuration.WebClientConfig;
-import org.oransc.policyagent.repository.Policy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-/**
- * Client for accessing the A1 adapter in the SDNC controller in ONAP
- */
-@SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally
-public class SdncOnapA1Client implements A1Client {
- @Value.Immutable
- @Gson.TypeAdapters
- interface SdncOnapAdapterInput {
- public String nearRtRicId();
-
- public Optional<String> policyTypeId();
-
- public Optional<String> policyInstanceId();
-
- public Optional<String> policyInstance();
-
- public Optional<List<String>> properties();
- }
-
- private static final String URL_PREFIX = "/A1-ADAPTER-API:";
-
- private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
-
- private final ControllerConfig controllerConfig;
- private final RicConfig ricConfig;
- private final AsyncRestClient restClient;
-
- public SdncOnapA1Client(RicConfig ricConfig, ControllerConfig controllerConfig, WebClientConfig clientConfig) {
- this(ricConfig, controllerConfig,
- new AsyncRestClient(controllerConfig.baseUrl() + "/restconf/operations", clientConfig));
- logger.debug("SdncOnapA1Client for ric: {}, a1ControllerBaseUrl: {}", ricConfig.name(),
- controllerConfig.baseUrl());
- }
-
- public SdncOnapA1Client(RicConfig ricConfig, ControllerConfig controllerConfig, AsyncRestClient restClient) {
- this.ricConfig = ricConfig;
- this.controllerConfig = controllerConfig;
- this.restClient = restClient;
- }
-
- @Override
- public Mono<List<String>> getPolicyTypeIdentities() {
- return getPolicyTypeIds() //
- .collectList();
- }
-
- @Override
- public Mono<List<String>> getPolicyIdentities() {
- return getPolicyTypeIds() //
- .flatMap(this::getPolicyIdentitiesByType) //
- .collectList();
- }
-
- @Override
- public Mono<String> getPolicyTypeSchema(String policyTypeId) {
- SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(ricConfig.baseUrl()) //
- .policyTypeId(policyTypeId) //
- .build();
- String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
- logger.debug("POST getPolicyType inputJsonString = {}", inputJsonString);
-
- return restClient
- .postWithAuthHeader(URL_PREFIX + "getPolicyType", inputJsonString, controllerConfig.userName(),
- controllerConfig.password()) //
- .flatMap(response -> SdncJsonHelper.getValueFromResponse(response, "policy-type")) //
- .flatMap(SdncJsonHelper::extractPolicySchema);
- }
-
- @Override
- public Mono<String> putPolicy(Policy policy) {
- SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(ricConfig.baseUrl()) //
- .policyTypeId(policy.type().name()) //
- .policyInstanceId(policy.id()) //
- .policyInstance(policy.json()) //
- .properties(new ArrayList<>()) //
- .build();
-
- String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
- logger.debug("POST putPolicy inputJsonString = {}", inputJsonString);
-
- return restClient.postWithAuthHeader(URL_PREFIX + "createPolicyInstance", inputJsonString,
- controllerConfig.userName(), controllerConfig.password());
- }
-
- @Override
- public Mono<String> deletePolicy(Policy policy) {
- return deletePolicyByTypeId(policy.type().name(), policy.id());
- }
-
- @Override
- public Flux<String> deleteAllPolicies() {
- return getPolicyTypeIds() //
- .flatMap(this::deletePoliciesForType); //
- }
-
- @Override
- public Mono<A1ProtocolType> getProtocolVersion() {
- return getPolicyTypeIdentities() //
- .flatMap(notUsed -> Mono.just(A1ProtocolType.SDNC_ONAP));
- }
-
- @Override
- public Mono<String> getPolicyStatus(Policy policy) {
- return Mono.error(new Exception("Status not implemented in the controller"));
- }
-
- private Flux<String> getPolicyTypeIds() {
- SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(ricConfig.baseUrl()) //
- .build();
- String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
- logger.debug("POST getPolicyTypeIdentities inputJsonString = {}", inputJsonString);
-
- return restClient
- .postWithAuthHeader(URL_PREFIX + "getPolicyTypes", inputJsonString, controllerConfig.userName(),
- controllerConfig.password()) //
- .flatMap(response -> SdncJsonHelper.getValueFromResponse(response, "policy-type-id-list")) //
- .flatMapMany(SdncJsonHelper::parseJsonArrayOfString);
- }
-
- private Flux<String> getPolicyIdentitiesByType(String policyTypeId) {
- SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(ricConfig.baseUrl()) //
- .policyTypeId(policyTypeId) //
- .build();
- String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
- logger.debug("POST getPolicyIdentities inputJsonString = {}", inputJsonString);
-
- return restClient
- .postWithAuthHeader(URL_PREFIX + "getPolicyInstances", inputJsonString, controllerConfig.userName(),
- controllerConfig.password()) //
- .flatMap(response -> SdncJsonHelper.getValueFromResponse(response, "policy-instance-id-list")) //
- .flatMapMany(SdncJsonHelper::parseJsonArrayOfString);
- }
-
- private Flux<String> deletePoliciesForType(String typeId) {
- return getPolicyIdentitiesByType(typeId) //
- .flatMap(policyId -> deletePolicyByTypeId(typeId, policyId)); //
- }
-
- private Mono<String> deletePolicyByTypeId(String policyTypeId, String policyId) {
- SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(ricConfig.baseUrl()) //
- .policyTypeId(policyTypeId) //
- .policyInstanceId(policyId) //
- .build();
- String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
- logger.debug("POST deletePolicy inputJsonString = {}", inputJsonString);
-
- return restClient.postWithAuthHeader(URL_PREFIX + "deletePolicyInstance", inputJsonString,
- controllerConfig.userName(), controllerConfig.password());
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import com.google.gson.FieldNamingPolicy;
-import com.google.gson.GsonBuilder;
-
-import java.lang.invoke.MethodHandles;
-import java.nio.charset.StandardCharsets;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-
-import org.immutables.value.Value;
-import org.json.JSONObject;
-import org.oransc.policyagent.configuration.ControllerConfig;
-import org.oransc.policyagent.configuration.RicConfig;
-import org.oransc.policyagent.configuration.WebClientConfig;
-import org.oransc.policyagent.repository.Policy;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-/**
- * Client for accessing the A1 adapter in the SDNC controller in OSC.
- */
-@SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally
-public class SdncOscA1Client implements A1Client {
-
- static final int CONCURRENCY_RIC = 1; // How may paralell requests that is sent to one NearRT RIC
-
- @Value.Immutable
- @org.immutables.gson.Gson.TypeAdapters
- public interface AdapterRequest {
- public String nearRtRicUrl();
-
- public Optional<String> body();
- }
-
- @Value.Immutable
- @org.immutables.gson.Gson.TypeAdapters
- public interface AdapterOutput {
- public Optional<String> body();
-
- public int httpStatus();
- }
-
- static com.google.gson.Gson gson = new GsonBuilder() //
- .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_DASHES) //
- .create(); //
-
- private static final String GET_POLICY_RPC = "getA1Policy";
- private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private final ControllerConfig controllerConfig;
- private final AsyncRestClient restClient;
- private final RicConfig ricConfig;
- private final A1ProtocolType protocolType;
-
- /**
- * Constructor that creates the REST client to use.
- *
- * @param protocolType the southbound protocol of the controller. Supported protocols are SDNC_OSC_STD_V1_1 and
- * SDNC_OSC_OSC_V1
- * @param ricConfig the configuration of the Ric to communicate with
- * @param controllerConfig the configuration of the SDNC controller to use
- *
- * @throws IllegalArgumentException when the protocolType is wrong.
- */
- public SdncOscA1Client(A1ProtocolType protocolType, RicConfig ricConfig, ControllerConfig controllerConfig,
- WebClientConfig clientConfig) {
- this(protocolType, ricConfig, controllerConfig,
- new AsyncRestClient(controllerConfig.baseUrl() + "/restconf/operations", clientConfig));
- logger.debug("SdncOscA1Client for ric: {}, a1Controller: {}", ricConfig.name(), controllerConfig);
- }
-
- /**
- * Constructor where the REST client to use is provided.
- *
- * @param protocolType the southbound protocol of the controller. Supported protocols are SDNC_OSC_STD_V1_1 and
- * SDNC_OSC_OSC_V1
- * @param ricConfig the configuration of the Ric to communicate with
- * @param controllerConfig the configuration of the SDNC controller to use
- * @param restClient the REST client to use
- *
- * @throws IllegalArgumentException when the protocolType is wrong.
- */
- public SdncOscA1Client(A1ProtocolType protocolType, RicConfig ricConfig, ControllerConfig controllerConfig,
- AsyncRestClient restClient) {
- if (!(A1ProtocolType.SDNC_OSC_STD_V1_1.equals(protocolType)
- || A1ProtocolType.SDNC_OSC_OSC_V1.equals(protocolType))) {
- throw new IllegalArgumentException("Protocol type must be " + A1ProtocolType.SDNC_OSC_STD_V1_1 + " or "
- + A1ProtocolType.SDNC_OSC_OSC_V1 + ", was: " + protocolType);
- }
- this.restClient = restClient;
- this.ricConfig = ricConfig;
- this.protocolType = protocolType;
- this.controllerConfig = controllerConfig;
- }
-
- @Override
- public Mono<List<String>> getPolicyTypeIdentities() {
- if (this.protocolType == A1ProtocolType.SDNC_OSC_STD_V1_1) {
- return Mono.just(Arrays.asList(""));
- } else {
- OscA1Client.UriBuilder uri = new OscA1Client.UriBuilder(ricConfig);
- final String ricUrl = uri.createPolicyTypesUri();
- return post(GET_POLICY_RPC, ricUrl, Optional.empty()) //
- .flatMapMany(SdncJsonHelper::parseJsonArrayOfString) //
- .collectList();
- }
-
- }
-
- @Override
- public Mono<List<String>> getPolicyIdentities() {
- return getPolicyIds() //
- .collectList();
- }
-
- @Override
- public Mono<String> getPolicyTypeSchema(String policyTypeId) {
- if (this.protocolType == A1ProtocolType.SDNC_OSC_STD_V1_1) {
- return Mono.just("{}");
- } else {
- OscA1Client.UriBuilder uri = new OscA1Client.UriBuilder(ricConfig);
- final String ricUrl = uri.createGetSchemaUri(policyTypeId);
- return post(GET_POLICY_RPC, ricUrl, Optional.empty()) //
- .flatMap(response -> OscA1Client.extractCreateSchema(response, policyTypeId));
- }
- }
-
- @Override
- public Mono<String> putPolicy(Policy policy) {
- return getUriBuilder() //
- .flatMap(builder -> {
- String ricUrl = builder.createPutPolicyUri(policy.type().name(), policy.id());
- return post("putA1Policy", ricUrl, Optional.of(policy.json()));
- });
- }
-
- @Override
- public Mono<String> deletePolicy(Policy policy) {
- return deletePolicyById(policy.type().name(), policy.id());
- }
-
- @Override
- public Flux<String> deleteAllPolicies() {
- if (this.protocolType == A1ProtocolType.SDNC_OSC_STD_V1_1) {
- return getPolicyIds() //
- .flatMap(policyId -> deletePolicyById("", policyId), CONCURRENCY_RIC); //
- } else {
- OscA1Client.UriBuilder uriBuilder = new OscA1Client.UriBuilder(ricConfig);
- return getPolicyTypeIdentities() //
- .flatMapMany(Flux::fromIterable) //
- .flatMap(type -> oscDeleteInstancesForType(uriBuilder, type), CONCURRENCY_RIC);
- }
- }
-
- private Flux<String> oscGetInstancesForType(OscA1Client.UriBuilder uriBuilder, String type) {
- return post(GET_POLICY_RPC, uriBuilder.createGetPolicyIdsUri(type), Optional.empty()) //
- .flatMapMany(SdncJsonHelper::parseJsonArrayOfString);
- }
-
- private Flux<String> oscDeleteInstancesForType(OscA1Client.UriBuilder uriBuilder, String type) {
- return oscGetInstancesForType(uriBuilder, type) //
- .flatMap(instance -> deletePolicyById(type, instance), CONCURRENCY_RIC);
- }
-
- @Override
- public Mono<A1ProtocolType> getProtocolVersion() {
- return tryStdProtocolVersion() //
- .onErrorResume(t -> tryOscProtocolVersion());
- }
-
- @Override
- public Mono<String> getPolicyStatus(Policy policy) {
- return getUriBuilder() //
- .flatMap(builder -> {
- String ricUrl = builder.createGetPolicyStatusUri(policy.type().name(), policy.id());
- return post("getA1PolicyStatus", ricUrl, Optional.empty());
- });
- }
-
- private Mono<A1UriBuilder> getUriBuilder() {
- if (protocolType == A1ProtocolType.SDNC_OSC_STD_V1_1) {
- return Mono.just(new StdA1ClientVersion1.UriBuilder(ricConfig));
- } else {
- return Mono.just(new OscA1Client.UriBuilder(ricConfig));
- }
- }
-
- private Mono<A1ProtocolType> tryOscProtocolVersion() {
- OscA1Client.UriBuilder oscApiuriBuilder = new OscA1Client.UriBuilder(ricConfig);
- return post(GET_POLICY_RPC, oscApiuriBuilder.createHealtcheckUri(), Optional.empty()) //
- .flatMap(x -> Mono.just(A1ProtocolType.SDNC_OSC_OSC_V1));
- }
-
- private Mono<A1ProtocolType> tryStdProtocolVersion() {
- StdA1ClientVersion1.UriBuilder uriBuilder = new StdA1ClientVersion1.UriBuilder(ricConfig);
- return post(GET_POLICY_RPC, uriBuilder.createGetPolicyIdsUri(), Optional.empty()) //
- .flatMap(x -> Mono.just(A1ProtocolType.SDNC_OSC_STD_V1_1));
- }
-
- private Flux<String> getPolicyIds() {
- if (this.protocolType == A1ProtocolType.SDNC_OSC_STD_V1_1) {
- StdA1ClientVersion1.UriBuilder uri = new StdA1ClientVersion1.UriBuilder(ricConfig);
- final String ricUrl = uri.createGetPolicyIdsUri();
- return post(GET_POLICY_RPC, ricUrl, Optional.empty()) //
- .flatMapMany(SdncJsonHelper::parseJsonArrayOfString);
- } else {
- OscA1Client.UriBuilder uri = new OscA1Client.UriBuilder(ricConfig);
- return getPolicyTypeIdentities() //
- .flatMapMany(Flux::fromIterable)
- .flatMap(type -> post(GET_POLICY_RPC, uri.createGetPolicyIdsUri(type), Optional.empty())) //
- .flatMap(SdncJsonHelper::parseJsonArrayOfString);
- }
- }
-
- private Mono<String> deletePolicyById(String type, String policyId) {
- return getUriBuilder() //
- .flatMap(builder -> {
- String ricUrl = builder.createDeleteUri(type, policyId);
- return post("deleteA1Policy", ricUrl, Optional.empty());
- });
- }
-
- private Mono<String> post(String rpcName, String ricUrl, Optional<String> body) {
- AdapterRequest inputParams = ImmutableAdapterRequest.builder() //
- .nearRtRicUrl(ricUrl) //
- .body(body) //
- .build();
- final String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
- logger.debug("POST inputJsonString = {}", inputJsonString);
-
- return restClient
- .postWithAuthHeader(controllerUrl(rpcName), inputJsonString, this.controllerConfig.userName(),
- this.controllerConfig.password()) //
- .flatMap(this::extractResponseBody);
- }
-
- private Mono<String> extractResponse(JSONObject responseOutput) {
- AdapterOutput output = gson.fromJson(responseOutput.toString(), ImmutableAdapterOutput.class);
- Optional<String> optionalBody = output.body();
- String body = optionalBody.isPresent() ? optionalBody.get() : "";
- if (HttpStatus.valueOf(output.httpStatus()).is2xxSuccessful()) {
- return Mono.just(body);
- } else {
- logger.debug("Error response: {} {}", output.httpStatus(), body);
- byte[] responseBodyBytes = body.getBytes(StandardCharsets.UTF_8);
- WebClientResponseException responseException = new WebClientResponseException(output.httpStatus(),
- "statusText", null, responseBodyBytes, StandardCharsets.UTF_8, null);
-
- return Mono.error(responseException);
- }
- }
-
- private Mono<String> extractResponseBody(String responseStr) {
- return SdncJsonHelper.getOutput(responseStr) //
- .flatMap(this::extractResponse);
- }
-
- private String controllerUrl(String rpcName) {
- return "/A1-ADAPTER-API:" + rpcName;
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.oransc.policyagent.configuration.RicConfig;
-import org.oransc.policyagent.configuration.WebClientConfig;
-import org.oransc.policyagent.repository.Policy;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-/**
- * Client for accessing standard A1 REST API version 1.1
- */
-public class StdA1ClientVersion1 implements A1Client {
-
- public static class UriBuilder implements A1UriBuilder {
-
- private final RicConfig ricConfig;
-
- public UriBuilder(RicConfig ricConfig) {
- this.ricConfig = ricConfig;
- }
-
- /**
- * /A1-P/v1/policies/{policyId}
- */
- @Override
- public String createPutPolicyUri(String type, String policyId) {
- return policiesBaseUri() + policyId;
- }
-
- /**
- * /A1-P/v1/policies
- */
- public String createGetPolicyIdsUri() {
- return baseUri() + "/policies";
- }
-
- /**
- * /A1-P/v1/policies/{policyId}
- */
- @Override
- public String createDeleteUri(String type, String policyId) {
- return policiesBaseUri() + policyId;
- }
-
- /**
- * /A1-P/v1/policies/{policyId}/status
- */
- public String createGetPolicyStatusUri(String type, String policyId) {
- return policiesBaseUri() + policyId + "/status";
- }
-
- private String baseUri() {
- return ricConfig.baseUrl() + "/A1-P/v1";
- }
-
- private String policiesBaseUri() {
- return createGetPolicyIdsUri() + "/";
- }
- }
-
- private final AsyncRestClient restClient;
- private final UriBuilder uri;
-
- public StdA1ClientVersion1(RicConfig ricConfig, WebClientConfig webClientConfig) {
- this(new AsyncRestClient("", webClientConfig), ricConfig);
- }
-
- public StdA1ClientVersion1(AsyncRestClient restClient, RicConfig ricConfig) {
- this.restClient = restClient;
- this.uri = new UriBuilder(ricConfig);
- }
-
- @Override
- public Mono<List<String>> getPolicyIdentities() {
- return getPolicyIds() //
- .collectList();
- }
-
- @Override
- public Mono<String> putPolicy(Policy policy) {
- return restClient.put(uri.createPutPolicyUri(policy.type().name(), policy.id()), policy.json());
- }
-
- @Override
- public Mono<List<String>> getPolicyTypeIdentities() {
- return Mono.just(Arrays.asList(""));
- }
-
- @Override
- public Mono<String> getPolicyTypeSchema(String policyTypeId) {
- return Mono.just("{}");
- }
-
- @Override
- public Mono<String> deletePolicy(Policy policy) {
- return deletePolicyById(policy.id());
- }
-
- @Override
- public Flux<String> deleteAllPolicies() {
- return getPolicyIds() //
- .flatMap(this::deletePolicyById); //
- }
-
- @Override
- public Mono<A1ProtocolType> getProtocolVersion() {
- return getPolicyIdentities() //
- .flatMap(x -> Mono.just(A1ProtocolType.STD_V1_1));
- }
-
- @Override
- public Mono<String> getPolicyStatus(Policy policy) {
- return restClient.get(uri.createGetPolicyStatusUri(policy.type().name(), policy.id()));
- }
-
- private Flux<String> getPolicyIds() {
- return restClient.get(uri.createGetPolicyIdsUri()) //
- .flatMapMany(SdncJsonHelper::parseJsonArrayOfString);
- }
-
- private Mono<String> deletePolicyById(String policyId) {
- return restClient.delete(uri.createDeleteUri("", policyId));
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.configuration;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.validation.constraints.NotEmpty;
-
-import lombok.Getter;
-
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.boot.context.properties.ConfigurationProperties;
-import org.springframework.boot.context.properties.EnableConfigurationProperties;
-import reactor.core.publisher.Flux;
-
-@EnableConfigurationProperties
-@ConfigurationProperties()
-public class ApplicationConfig {
- @NotEmpty
- @Getter
- @Value("${app.filepath}")
- private String localConfigurationFilePath;
-
- @Value("${server.ssl.key-store-type}")
- private String sslKeyStoreType = "";
-
- @Value("${server.ssl.key-store-password}")
- private String sslKeyStorePassword = "";
-
- @Value("${server.ssl.key-store}")
- private String sslKeyStore = "";
-
- @Value("${server.ssl.key-password}")
- private String sslKeyPassword = "";
-
- @Value("${app.webclient.trust-store-used}")
- private boolean sslTrustStoreUsed = false;
-
- @Value("${app.webclient.trust-store-password}")
- private String sslTrustStorePassword = "";
-
- @Value("${app.webclient.trust-store}")
- private String sslTrustStore = "";
-
- private Map<String, RicConfig> ricConfigs = new HashMap<>();
-
- @Getter
- private String dmaapConsumerTopicUrl;
-
- @Getter
- private String dmaapProducerTopicUrl;
-
- private Map<String, ControllerConfig> controllerConfigs = new HashMap<>();
-
- public synchronized Collection<RicConfig> getRicConfigs() {
- return this.ricConfigs.values();
- }
-
- public WebClientConfig getWebClientConfig() {
- return ImmutableWebClientConfig.builder() //
- .keyStoreType(this.sslKeyStoreType) //
- .keyStorePassword(this.sslKeyStorePassword) //
- .keyStore(this.sslKeyStore) //
- .keyPassword(this.sslKeyPassword) //
- .isTrustStoreUsed(this.sslTrustStoreUsed) //
- .trustStore(this.sslTrustStore) //
- .trustStorePassword(this.sslTrustStorePassword) //
- .build();
- }
-
- public synchronized ControllerConfig getControllerConfig(String name) throws ServiceException {
- ControllerConfig controllerConfig = this.controllerConfigs.get(name);
- if (controllerConfig == null) {
- throw new ServiceException("Could not find controller config: " + name);
- }
- return controllerConfig;
- }
-
- public synchronized RicConfig getRic(String ricName) throws ServiceException {
- RicConfig ricConfig = this.ricConfigs.get(ricName);
- if (ricConfig == null) {
- throw new ServiceException("Could not find ric configuration: " + ricName);
- }
- return ricConfig;
- }
-
- public static class RicConfigUpdate {
- public enum Type {
- ADDED, CHANGED, REMOVED
- }
-
- @Getter
- private final RicConfig ricConfig;
- @Getter
- private final Type type;
-
- RicConfigUpdate(RicConfig ric, Type event) {
- this.ricConfig = ric;
- this.type = event;
- }
- }
-
- public synchronized Flux<RicConfigUpdate> setConfiguration(
- ApplicationConfigParser.ConfigParserResult parserResult) {
-
- Collection<RicConfigUpdate> modifications = new ArrayList<>();
- this.controllerConfigs = parserResult.controllerConfigs();
-
- this.dmaapConsumerTopicUrl = parserResult.dmaapConsumerTopicUrl();
- this.dmaapProducerTopicUrl = parserResult.dmaapProducerTopicUrl();
-
- Map<String, RicConfig> newRicConfigs = new HashMap<>();
- for (RicConfig newConfig : parserResult.ricConfigs()) {
- RicConfig oldConfig = this.ricConfigs.get(newConfig.name());
- this.ricConfigs.remove(newConfig.name());
- if (oldConfig == null) {
- newRicConfigs.put(newConfig.name(), newConfig);
- modifications.add(new RicConfigUpdate(newConfig, RicConfigUpdate.Type.ADDED));
- } else if (!newConfig.equals(oldConfig)) {
- modifications.add(new RicConfigUpdate(newConfig, RicConfigUpdate.Type.CHANGED));
- newRicConfigs.put(newConfig.name(), newConfig);
- } else {
- newRicConfigs.put(oldConfig.name(), oldConfig);
- }
- }
- for (RicConfig deletedConfig : this.ricConfigs.values()) {
- modifications.add(new RicConfigUpdate(deletedConfig, RicConfigUpdate.Type.REMOVED));
- }
- this.ricConfigs = newRicConfigs;
-
- return Flux.fromIterable(modifications);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.configuration;
-
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Map.Entry;
-import java.util.Set;
-
-import javax.validation.constraints.NotNull;
-
-import org.immutables.gson.Gson;
-import org.immutables.value.Value;
-import org.oransc.policyagent.exceptions.ServiceException;
-
-/**
- * Parser for the Json representing of the component configuration.
- */
-public class ApplicationConfigParser {
-
- private static final String CONFIG = "config";
- private static final String CONTROLLER = "controller";
-
- @Value.Immutable
- @Gson.TypeAdapters
- public interface ConfigParserResult {
- List<RicConfig> ricConfigs();
-
- Map<String, ControllerConfig> controllerConfigs();
-
- String dmaapConsumerTopicUrl();
-
- String dmaapProducerTopicUrl();
-
- }
-
- public ConfigParserResult parse(JsonObject root) throws ServiceException {
-
- String dmaapProducerTopicUrl = "";
- String dmaapConsumerTopicUrl = "";
-
- JsonObject agentConfigJson = root.getAsJsonObject(CONFIG);
-
- if (agentConfigJson == null) {
- throw new ServiceException("Missing root configuration \"" + CONFIG + "\" in JSON: " + root);
- }
-
- JsonObject json = agentConfigJson.getAsJsonObject("streams_publishes");
- if (json != null) {
- dmaapProducerTopicUrl = parseDmaapConfig(json);
- }
-
- json = agentConfigJson.getAsJsonObject("streams_subscribes");
- if (json != null) {
- dmaapConsumerTopicUrl = parseDmaapConfig(json);
- }
-
- List<RicConfig> ricConfigs = parseRics(agentConfigJson);
- Map<String, ControllerConfig> controllerConfigs = parseControllerConfigs(agentConfigJson);
- checkConfigurationConsistency(ricConfigs, controllerConfigs);
-
- return ImmutableConfigParserResult.builder() //
- .dmaapConsumerTopicUrl(dmaapConsumerTopicUrl) //
- .dmaapProducerTopicUrl(dmaapProducerTopicUrl) //
- .ricConfigs(ricConfigs) //
- .controllerConfigs(controllerConfigs) //
- .build();
- }
-
- private void checkConfigurationConsistency(List<RicConfig> ricConfigs,
- Map<String, ControllerConfig> controllerConfigs) throws ServiceException {
- Set<String> ricUrls = new HashSet<>();
- Set<String> ricNames = new HashSet<>();
- for (RicConfig ric : ricConfigs) {
- if (!ricUrls.add(ric.baseUrl())) {
- throw new ServiceException("Configuration error, more than one RIC URL: " + ric.baseUrl());
- }
- if (!ricNames.add(ric.name())) {
- throw new ServiceException("Configuration error, more than one RIC with name: " + ric.name());
- }
- if (!ric.controllerName().isEmpty() && controllerConfigs.get(ric.controllerName()) == null) {
- throw new ServiceException(
- "Configuration error, controller configuration not found: " + ric.controllerName());
- }
-
- }
- }
-
- private List<RicConfig> parseRics(JsonObject config) throws ServiceException {
- List<RicConfig> result = new ArrayList<>();
- for (JsonElement ricElem : getAsJsonArray(config, "ric")) {
- JsonObject ricAsJson = ricElem.getAsJsonObject();
- JsonElement controllerNameElement = ricAsJson.get(CONTROLLER);
- ImmutableRicConfig ricConfig = ImmutableRicConfig.builder() //
- .name(get(ricAsJson, "name").getAsString()) //
- .baseUrl(get(ricAsJson, "baseUrl").getAsString()) //
- .managedElementIds(parseManagedElementIds(get(ricAsJson, "managedElementIds").getAsJsonArray())) //
- .controllerName(controllerNameElement != null ? controllerNameElement.getAsString() : "") //
- .build();
- result.add(ricConfig);
- }
- return result;
- }
-
- Map<String, ControllerConfig> parseControllerConfigs(JsonObject config) throws ServiceException {
- if (config.get(CONTROLLER) == null) {
- return new HashMap<>();
- }
- Map<String, ControllerConfig> result = new HashMap<>();
- for (JsonElement element : getAsJsonArray(config, CONTROLLER)) {
- JsonObject controllerAsJson = element.getAsJsonObject();
- ImmutableControllerConfig controllerConfig = ImmutableControllerConfig.builder() //
- .name(get(controllerAsJson, "name").getAsString()) //
- .baseUrl(get(controllerAsJson, "baseUrl").getAsString()) //
- .password(get(controllerAsJson, "password").getAsString()) //
- .userName(get(controllerAsJson, "userName").getAsString()) // )
- .build();
-
- if (result.put(controllerConfig.name(), controllerConfig) != null) {
- throw new ServiceException(
- "Configuration error, more than one controller with name: " + controllerConfig.name());
- }
- }
- return result;
- }
-
- private List<String> parseManagedElementIds(JsonArray asJsonObject) {
- Iterator<JsonElement> iterator = asJsonObject.iterator();
- List<String> managedElementIds = new ArrayList<>();
- while (iterator.hasNext()) {
- managedElementIds.add(iterator.next().getAsString());
-
- }
- return managedElementIds;
- }
-
- private static JsonElement get(JsonObject obj, String memberName) throws ServiceException {
- JsonElement elem = obj.get(memberName);
- if (elem == null) {
- throw new ServiceException("Could not find member: '" + memberName + "' in: " + obj);
- }
- return elem;
- }
-
- private JsonArray getAsJsonArray(JsonObject obj, String memberName) throws ServiceException {
- return get(obj, memberName).getAsJsonArray();
- }
-
- private String parseDmaapConfig(JsonObject streamCfg) throws ServiceException {
- Set<Entry<String, JsonElement>> streamConfigEntries = streamCfg.entrySet();
- if (streamConfigEntries.size() != 1) {
- throw new ServiceException(
- "Invalid configuration. Number of streams must be one, config: " + streamConfigEntries);
- }
- JsonObject streamConfigEntry = streamConfigEntries.iterator().next().getValue().getAsJsonObject();
- JsonObject dmaapInfo = get(streamConfigEntry, "dmaap_info").getAsJsonObject();
- return getAsString(dmaapInfo, "topic_url");
- }
-
- private static @NotNull String getAsString(JsonObject obj, String memberName) throws ServiceException {
- return get(obj, memberName).getAsString();
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.configuration;
-
-import java.util.concurrent.Executor;
-
-import org.springframework.context.annotation.Bean;
-import org.springframework.context.annotation.Configuration;
-import org.springframework.scheduling.annotation.AsyncConfigurer;
-import org.springframework.scheduling.annotation.EnableAsync;
-import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
-
-@Configuration
-@EnableAsync
-public class AsyncConfiguration implements AsyncConfigurer {
-
- @Override
- @Bean(name = "threadPoolTaskExecutor")
- public Executor getAsyncExecutor() {
- // Set this configuration value from common properties file
- ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
- executor.setCorePoolSize(5);
- executor.setMaxPoolSize(10);
- executor.setQueueCapacity(25);
- return executor;
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.configuration;
-
-import org.immutables.value.Value;
-
-@Value.Immutable
-@Value.Style(redactedMask = "####")
-
-public interface ControllerConfig {
- public String name();
-
- public String baseUrl();
-
- public String userName();
-
- @Value.Redacted
- public String password();
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.configuration;
-
-import com.google.common.collect.ImmutableList;
-
-import org.immutables.value.Value;
-
-@Value.Immutable
-public interface RicConfig {
- public String name();
-
- public String controllerName();
-
- public String baseUrl();
-
- public ImmutableList<String> managedElementIds();
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.configuration;
-
-import org.immutables.value.Value;
-
-@Value.Immutable
-@Value.Style(redactedMask = "####")
-public interface WebClientConfig {
- public String keyStoreType();
-
- @Value.Redacted
- public String keyStorePassword();
-
- public String keyStore();
-
- @Value.Redacted
- public String keyPassword();
-
- public boolean isTrustStoreUsed();
-
- @Value.Redacted
- public String trustStorePassword();
-
- public String trustStore();
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.controllers;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-
-import java.lang.invoke.MethodHandles;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-
-import lombok.Getter;
-
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.oransc.policyagent.repository.ImmutablePolicy;
-import org.oransc.policyagent.repository.Lock.LockType;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Rics;
-import org.oransc.policyagent.repository.Service;
-import org.oransc.policyagent.repository.Services;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-import reactor.core.publisher.Mono;
-
-@RestController
-@Api(tags = "A1 Policy Management")
-public class PolicyController {
-
- public static class RejectionException extends Exception {
- private static final long serialVersionUID = 1L;
- @Getter
- private final HttpStatus status;
-
- public RejectionException(String message, HttpStatus status) {
- super(message);
- this.status = status;
- }
- }
-
- @Autowired
- private Rics rics;
- @Autowired
- private PolicyTypes policyTypes;
- @Autowired
- private Policies policies;
- @Autowired
- private A1ClientFactory a1ClientFactory;
- @Autowired
- private Services services;
-
- private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private static Gson gson = new GsonBuilder() //
- .serializeNulls() //
- .create(); //
-
- @GetMapping("/policy_schemas")
- @ApiOperation(value = "Returns policy type schema definitions")
- @ApiResponses(
- value = {
- @ApiResponse(code = 200, message = "Policy schemas", response = Object.class, responseContainer = "List"), //
- @ApiResponse(code = 404, message = "RIC is not found", response = String.class)})
- public ResponseEntity<String> getPolicySchemas( //
- @ApiParam(name = "ric", required = false, value = "The name of the Near-RT RIC to get the definitions for.") //
- @RequestParam(name = "ric", required = false) String ricName) {
- if (ricName == null) {
- Collection<PolicyType> types = this.policyTypes.getAll();
- return new ResponseEntity<>(toPolicyTypeSchemasJson(types), HttpStatus.OK);
- } else {
- try {
- Collection<PolicyType> types = rics.getRic(ricName).getSupportedPolicyTypes();
- return new ResponseEntity<>(toPolicyTypeSchemasJson(types), HttpStatus.OK);
- } catch (ServiceException e) {
- return new ResponseEntity<>(e.toString(), HttpStatus.NOT_FOUND);
- }
- }
- }
-
- @GetMapping("/policy_schema")
- @ApiOperation(value = "Returns one policy type schema definition")
- @ApiResponses(
- value = { //
- @ApiResponse(code = 200, message = "Policy schema", response = Object.class),
- @ApiResponse(code = 404, message = "RIC is not found", response = String.class)})
- public ResponseEntity<String> getPolicySchema( //
- @ApiParam(name = "id", required = true, value = "The ID of the policy type to get the definition for.") //
- @RequestParam(name = "id", required = true) String id) {
- try {
- PolicyType type = policyTypes.getType(id);
- return new ResponseEntity<>(type.schema(), HttpStatus.OK);
- } catch (ServiceException e) {
- return new ResponseEntity<>(e.toString(), HttpStatus.NOT_FOUND);
- }
- }
-
- @GetMapping("/policy_types")
- @ApiOperation(value = "Query policy type names")
- @ApiResponses(
- value = {
- @ApiResponse(
- code = 200,
- message = "Policy type names",
- response = String.class,
- responseContainer = "List"),
- @ApiResponse(code = 404, message = "RIC is not found", response = String.class)})
- public ResponseEntity<String> getPolicyTypes( //
- @ApiParam(name = "ric", required = false, value = "The name of the Near-RT RIC to get types for.") //
- @RequestParam(name = "ric", required = false) String ricName) {
- if (ricName == null) {
- Collection<PolicyType> types = this.policyTypes.getAll();
- return new ResponseEntity<>(toPolicyTypeIdsJson(types), HttpStatus.OK);
- } else {
- try {
- Collection<PolicyType> types = rics.getRic(ricName).getSupportedPolicyTypes();
- return new ResponseEntity<>(toPolicyTypeIdsJson(types), HttpStatus.OK);
- } catch (ServiceException e) {
- return new ResponseEntity<>(e.toString(), HttpStatus.NOT_FOUND);
- }
- }
- }
-
- @GetMapping("/policy")
- @ApiOperation(value = "Returns a policy configuration") //
- @ApiResponses(
- value = { //
- @ApiResponse(code = 200, message = "Policy found", response = Object.class), //
- @ApiResponse(code = 404, message = "Policy is not found")} //
- )
- public ResponseEntity<String> getPolicy( //
- @ApiParam(name = "id", required = true, value = "The ID of the policy instance.") //
- @RequestParam(name = "id", required = true) String id) {
- try {
- Policy p = policies.getPolicy(id);
- return new ResponseEntity<>(p.json(), HttpStatus.OK);
- } catch (ServiceException e) {
- return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
- }
- }
-
- @DeleteMapping("/policy")
- @ApiOperation(value = "Delete a policy", response = Object.class)
- @ApiResponses(
- value = { //
- @ApiResponse(code = 204, message = "Policy deleted", response = Object.class),
- @ApiResponse(code = 404, message = "Policy is not found", response = String.class),
- @ApiResponse(code = 423, message = "RIC is not operational", response = String.class)})
- public Mono<ResponseEntity<Object>> deletePolicy( //
- @ApiParam(name = "id", required = true, value = "The ID of the policy instance.") //
- @RequestParam(name = "id", required = true) String id) {
- try {
- Policy policy = policies.getPolicy(id);
- keepServiceAlive(policy.ownerServiceName());
- Ric ric = policy.ric();
- return ric.getLock().lock(LockType.SHARED) //
- .flatMap(notUsed -> assertRicStateIdle(ric)) //
- .flatMap(notUsed -> a1ClientFactory.createA1Client(policy.ric())) //
- .doOnNext(notUsed -> policies.remove(policy)) //
- .flatMap(client -> client.deletePolicy(policy)) //
- .doOnNext(notUsed -> ric.getLock().unlockBlocking()) //
- .doOnError(notUsed -> ric.getLock().unlockBlocking()) //
- .flatMap(notUsed -> Mono.just(new ResponseEntity<>(HttpStatus.NO_CONTENT)))
- .onErrorResume(this::handleException);
- } catch (ServiceException e) {
- return Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND));
- }
- }
-
- @PutMapping(path = "/policy")
- @ApiOperation(value = "Put a policy", response = String.class)
- @ApiResponses(
- value = { //
- @ApiResponse(code = 201, message = "Policy created", response = Object.class), //
- @ApiResponse(code = 200, message = "Policy updated", response = Object.class), //
- @ApiResponse(code = 423, message = "RIC is not operational", response = String.class), //
- @ApiResponse(code = 404, message = "RIC or policy type is not found", response = String.class) //
- })
- public Mono<ResponseEntity<Object>> putPolicy( //
- @ApiParam(name = "type", required = false, value = "The name of the policy type.") //
- @RequestParam(name = "type", required = false, defaultValue = "") String typeName, //
- @ApiParam(name = "id", required = true, value = "The ID of the policy instance.") //
- @RequestParam(name = "id", required = true) String instanceId, //
- @ApiParam(name = "ric", required = true, value = "The name of the Near-RT RIC where the policy will be " + //
- "created.") //
- @RequestParam(name = "ric", required = true) String ricName, //
- @ApiParam(name = "service", required = true, value = "The name of the service creating the policy.") //
- @RequestParam(name = "service", required = true) String service, //
- @ApiParam(name = "transient", required = false, value = "If the policy is transient or not (boolean " + //
- "defaulted to false). A policy is transient if it will be forgotten when the service needs to " + //
- "reconnect to the Near-RT RIC.") //
- @RequestParam(name = "transient", required = false, defaultValue = "false") boolean isTransient, //
- @RequestBody Object jsonBody) {
-
- String jsonString = gson.toJson(jsonBody);
- Ric ric = rics.get(ricName);
- PolicyType type = policyTypes.get(typeName);
- keepServiceAlive(service);
- if (ric == null || type == null) {
- return Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND));
- }
- Policy policy = ImmutablePolicy.builder() //
- .id(instanceId) //
- .json(jsonString) //
- .type(type) //
- .ric(ric) //
- .ownerServiceName(service) //
- .lastModified(getTimeStampUtc()) //
- .isTransient(isTransient) //
- .build();
-
- final boolean isCreate = this.policies.get(policy.id()) == null;
-
- return ric.getLock().lock(LockType.SHARED) //
- .flatMap(notUsed -> assertRicStateIdle(ric)) //
- .flatMap(notUsed -> checkSupportedType(ric, type)) //
- .flatMap(notUsed -> validateModifiedPolicy(policy)) //
- .flatMap(notUsed -> a1ClientFactory.createA1Client(ric)) //
- .flatMap(client -> client.putPolicy(policy)) //
- .doOnNext(notUsed -> policies.put(policy)) //
- .doOnNext(notUsed -> ric.getLock().unlockBlocking()) //
- .doOnError(trowable -> ric.getLock().unlockBlocking()) //
- .flatMap(notUsed -> Mono.just(new ResponseEntity<>(isCreate ? HttpStatus.CREATED : HttpStatus.OK))) //
- .onErrorResume(this::handleException);
- }
-
- @SuppressWarnings({"unchecked"})
- private <T> Mono<ResponseEntity<T>> createResponseEntity(String message, HttpStatus status) {
- ResponseEntity<T> re = new ResponseEntity<>((T) message, status);
- return Mono.just(re);
- }
-
- private <T> Mono<ResponseEntity<T>> handleException(Throwable throwable) {
- if (throwable instanceof WebClientResponseException) {
- WebClientResponseException e = (WebClientResponseException) throwable;
- return createResponseEntity(e.getResponseBodyAsString(), e.getStatusCode());
- } else if (throwable instanceof RejectionException) {
- RejectionException e = (RejectionException) throwable;
- return createResponseEntity(e.getMessage(), e.getStatus());
- } else {
- return createResponseEntity(throwable.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
- }
- }
-
- private Mono<Object> validateModifiedPolicy(Policy policy) {
- // Check that ric is not updated
- Policy current = this.policies.get(policy.id());
- if (current != null && !current.ric().name().equals(policy.ric().name())) {
- RejectionException e = new RejectionException("Policy cannot change RIC, policyId: " + current.id() + //
- ", RIC name: " + current.ric().name() + //
- ", new name: " + policy.ric().name(), HttpStatus.CONFLICT);
- logger.debug("Request rejected, {}", e.getMessage());
- return Mono.error(e);
- }
- return Mono.just("OK");
- }
-
- private Mono<Object> checkSupportedType(Ric ric, PolicyType type) {
- if (!ric.isSupportingType(type.name())) {
- logger.debug("Request rejected, type not supported, RIC: {}", ric);
- RejectionException e = new RejectionException(
- "Type: " + type.name() + " not supported by RIC: " + ric.name(), HttpStatus.NOT_FOUND);
- return Mono.error(e);
- }
- return Mono.just("OK");
- }
-
- private Mono<Object> assertRicStateIdle(Ric ric) {
- if (ric.getState() == Ric.RicState.AVAILABLE) {
- return Mono.just("OK");
- } else {
- logger.debug("Request rejected RIC not IDLE, ric: {}", ric);
- RejectionException e = new RejectionException(
- "Ric is not operational, RIC name: " + ric.name() + ", state: " + ric.getState(), HttpStatus.LOCKED);
- return Mono.error(e);
- }
- }
-
- @GetMapping("/policies")
- @ApiOperation(value = "Query policies")
- @ApiResponses(
- value = {
- @ApiResponse(code = 200, message = "Policies", response = PolicyInfo.class, responseContainer = "List"),
- @ApiResponse(code = 404, message = "RIC or type not found", response = String.class)})
- public ResponseEntity<String> getPolicies( //
- @ApiParam(name = "type", required = false, value = "The name of the policy type to get policies for.") //
- @RequestParam(name = "type", required = false) String type, //
- @ApiParam(name = "ric", required = false, value = "The name of the Near-RT RIC to get policies for.") //
- @RequestParam(name = "ric", required = false) String ric, //
- @ApiParam(name = "service", required = false, value = "The name of the service to get policies for.") //
- @RequestParam(name = "service", required = false) String service) //
- {
- if ((type != null && this.policyTypes.get(type) == null)) {
- return new ResponseEntity<>("Policy type not found", HttpStatus.NOT_FOUND);
- }
- if ((ric != null && this.rics.get(ric) == null)) {
- return new ResponseEntity<>("RIC not found", HttpStatus.NOT_FOUND);
- }
-
- String filteredPolicies = policiesToJson(filter(type, ric, service));
- return new ResponseEntity<>(filteredPolicies, HttpStatus.OK);
- }
-
- @GetMapping("/policy_ids")
- @ApiOperation(value = "Query policies, only IDs returned")
- @ApiResponses(
- value = {@ApiResponse(code = 200, message = "Policy ids", response = String.class, responseContainer = "List"),
- @ApiResponse(code = 404, message = "RIC or type not found", response = String.class)})
- public ResponseEntity<String> getPolicyIds( //
- @ApiParam(name = "type", required = false, value = "The name of the policy type to get policies for.") //
- @RequestParam(name = "type", required = false) String type, //
- @ApiParam(name = "ric", required = false, value = "The name of the Near-RT RIC to get policies for.") //
- @RequestParam(name = "ric", required = false) String ric, //
- @ApiParam(name = "service", required = false, value = "The name of the service to get policies for.") //
- @RequestParam(name = "service", required = false) String service) //
- {
- if ((type != null && this.policyTypes.get(type) == null)) {
- return new ResponseEntity<>("Policy type not found", HttpStatus.NOT_FOUND);
- }
- if ((ric != null && this.rics.get(ric) == null)) {
- return new ResponseEntity<>("RIC not found", HttpStatus.NOT_FOUND);
- }
-
- String policyIdsJson = toPolicyIdsJson(filter(type, ric, service));
- return new ResponseEntity<>(policyIdsJson, HttpStatus.OK);
- }
-
- @GetMapping("/policy_status")
- @ApiOperation(value = "Returns a policy status") //
- @ApiResponses(
- value = { //
- @ApiResponse(code = 200, message = "Policy status", response = Object.class), //
- @ApiResponse(code = 404, message = "Policy is not found", response = String.class)} //
- )
- public Mono<ResponseEntity<String>> getPolicyStatus( //
- @ApiParam(name = "id", required = true, value = "The ID of the policy.") @RequestParam(
- name = "id", //
- required = true) String id) {
- try {
- Policy policy = policies.getPolicy(id);
-
- return a1ClientFactory.createA1Client(policy.ric()) //
- .flatMap(client -> client.getPolicyStatus(policy)) //
- .flatMap(status -> Mono.just(new ResponseEntity<>(status, HttpStatus.OK)))
- .onErrorResume(this::handleException);
- } catch (ServiceException e) {
- return Mono.just(new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND));
- }
- }
-
- private void keepServiceAlive(String name) {
- Service s = this.services.get(name);
- if (s != null) {
- s.keepAlive();
- }
- }
-
- private boolean include(String filter, String value) {
- return filter == null || value.equals(filter);
- }
-
- private Collection<Policy> filter(Collection<Policy> collection, String type, String ric, String service) {
- if (type == null && ric == null && service == null) {
- return collection;
- }
- List<Policy> filtered = new ArrayList<>();
- for (Policy p : collection) {
- if (include(type, p.type().name()) && include(ric, p.ric().name())
- && include(service, p.ownerServiceName())) {
- filtered.add(p);
- }
- }
- return filtered;
- }
-
- private Collection<Policy> filter(String type, String ric, String service) {
- if (type != null) {
- return filter(policies.getForType(type), null, ric, service);
- } else if (service != null) {
- return filter(policies.getForService(service), type, ric, null);
- } else if (ric != null) {
- return filter(policies.getForRic(ric), type, null, service);
- } else {
- return policies.getAll();
- }
- }
-
- private String policiesToJson(Collection<Policy> policies) {
- List<PolicyInfo> v = new ArrayList<>(policies.size());
- for (Policy p : policies) {
- PolicyInfo policyInfo = new PolicyInfo();
- policyInfo.id = p.id();
- policyInfo.json = fromJson(p.json());
- policyInfo.ric = p.ric().name();
- policyInfo.type = p.type().name();
- policyInfo.service = p.ownerServiceName();
- policyInfo.lastModified = p.lastModified();
- if (!policyInfo.validate()) {
- logger.error("BUG, all fields must be set");
- }
- v.add(policyInfo);
- }
- return gson.toJson(v);
- }
-
- private Object fromJson(String jsonStr) {
- return gson.fromJson(jsonStr, Object.class);
- }
-
- private String toPolicyTypeSchemasJson(Collection<PolicyType> types) {
- StringBuilder result = new StringBuilder();
- result.append("[");
- boolean first = true;
- for (PolicyType t : types) {
- if (!first) {
- result.append(",");
- }
- first = false;
- result.append(t.schema());
- }
- result.append("]");
- return result.toString();
- }
-
- private String toPolicyTypeIdsJson(Collection<PolicyType> types) {
- List<String> v = new ArrayList<>(types.size());
- for (PolicyType t : types) {
- v.add(t.name());
- }
- return gson.toJson(v);
- }
-
- private String toPolicyIdsJson(Collection<Policy> policies) {
- List<String> v = new ArrayList<>(policies.size());
- for (Policy p : policies) {
- v.add(p.id());
- }
- return gson.toJson(v);
- }
-
- private String getTimeStampUtc() {
- return java.time.Instant.now().toString();
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.controllers;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-import org.immutables.gson.Gson;
-
-@Gson.TypeAdapters
-@ApiModel(value = "PolicyInfo")
-public class PolicyInfo {
-
- @ApiModelProperty(value = "identity of the policy")
- public String id;
-
- @ApiModelProperty(value = "name of the policy type")
- public String type;
-
- @ApiModelProperty(value = "identity of the target Near-RT RIC")
- public String ric;
-
- @ApiModelProperty(value = "the configuration of the policy")
- public Object json;
-
- @ApiModelProperty(value = "the name of the service owning the policy")
- public String service;
-
- @ApiModelProperty(value = "timestamp, last modification time")
- public String lastModified;
-
- PolicyInfo() {
- }
-
- public boolean validate() {
- return id != null && type != null && ric != null && json != null && service != null && lastModified != null;
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.controllers;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-import java.util.Collection;
-
-import org.immutables.gson.Gson;
-
-@Gson.TypeAdapters
-@ApiModel(value = "RicInfo")
-class RicInfo {
- @ApiModelProperty(value = "identity of the ric")
- public final String ricName;
-
- @ApiModelProperty(value = "O1 identities for managed entities")
- public final Collection<String> managedElementIds;
-
- @ApiModelProperty(value = "supported policy types")
- public final Collection<String> policyTypes;
-
- @ApiModelProperty(value = "state info")
- public final String state;
-
- RicInfo(String name, Collection<String> managedElementIds, Collection<String> policyTypes, String state) {
- this.ricName = name;
- this.managedElementIds = managedElementIds;
- this.policyTypes = policyTypes;
- this.state = state;
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.controllers;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Rics;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
-@RestController
-@Api(tags = "RIC Repository")
-public class RicRepositoryController {
-
- @Autowired
- private Rics rics;
-
- @Autowired
- PolicyTypes types;
-
- private static Gson gson = new GsonBuilder() //
- .serializeNulls() //
- .create(); //
-
- /**
- * Example: http://localhost:8081/rics?managedElementId=kista_1
- */
- @GetMapping("/ric")
- @ApiOperation(value = "Returns the name of a RIC managing one Mananged Element")
- @ApiResponses(
- value = { //
- @ApiResponse(code = 200, message = "RIC is found", response = String.class), //
- @ApiResponse(code = 404, message = "RIC is not found", response = String.class) //
- })
- public ResponseEntity<String> getRic( //
- @ApiParam(name = "managedElementId", required = true, value = "The ID of the Managed Element") //
- @RequestParam(name = "managedElementId", required = true) String managedElementId) {
- Optional<Ric> ric = this.rics.lookupRicForManagedElement(managedElementId);
-
- if (ric.isPresent()) {
- return new ResponseEntity<>(ric.get().name(), HttpStatus.OK);
- } else {
- return new ResponseEntity<>("No RIC found", HttpStatus.NOT_FOUND);
- }
- }
-
- /**
- * @return a Json array of all RIC data Example: http://localhost:8081/ric
- */
- @GetMapping("/rics")
- @ApiOperation(value = "Query Near-RT RIC information")
- @ApiResponses(
- value = { //
- @ApiResponse(code = 200, message = "OK", response = RicInfo.class, responseContainer = "List"), //
- @ApiResponse(code = 404, message = "Policy type is not found", response = String.class)})
- public ResponseEntity<String> getRics( //
- @ApiParam(name = "policyType", required = false, value = "The name of the policy type") //
- @RequestParam(name = "policyType", required = false) String supportingPolicyType) {
- if ((supportingPolicyType != null) && (this.types.get(supportingPolicyType) == null)) {
- return new ResponseEntity<>("Policy type not found", HttpStatus.NOT_FOUND);
- }
-
- List<RicInfo> result = new ArrayList<>();
- for (Ric ric : rics.getRics()) {
- if (supportingPolicyType == null || ric.isSupportingType(supportingPolicyType)) {
- result.add(new RicInfo(ric.name(), ric.getManagedElementIds(), ric.getSupportedPolicyTypeNames(),
- ric.getState().toString()));
- }
- }
-
- return new ResponseEntity<>(gson.toJson(result), HttpStatus.OK);
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.controllers;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiParam;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.Collection;
-
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.Service;
-import org.oransc.policyagent.repository.Services;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.DeleteMapping;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.PutMapping;
-import org.springframework.web.bind.annotation.RequestBody;
-import org.springframework.web.bind.annotation.RequestParam;
-import org.springframework.web.bind.annotation.RestController;
-
-@RestController
-@Api(tags = "Service registry and supervision")
-public class ServiceController {
-
- private final Services services;
- private final Policies policies;
-
- private static Gson gson = new GsonBuilder() //
- .create(); //
-
- @Autowired
- ServiceController(Services services, Policies policies) {
- this.services = services;
- this.policies = policies;
- }
-
- @GetMapping("/services")
- @ApiOperation(value = "Returns service information")
- @ApiResponses(
- value = { //
- @ApiResponse(code = 200, message = "OK", response = ServiceStatus.class, responseContainer = "List"), //
- @ApiResponse(code = 404, message = "Service is not found", response = String.class)})
- public ResponseEntity<String> getServices(//
- @ApiParam(name = "name", required = false, value = "The name of the service") //
- @RequestParam(name = "name", required = false) String name) {
- if (name != null && this.services.get(name) == null) {
- return new ResponseEntity<>("Service not found", HttpStatus.NOT_FOUND);
- }
-
- Collection<ServiceStatus> servicesStatus = new ArrayList<>();
- for (Service s : this.services.getAll()) {
- if (name == null || name.equals(s.getName())) {
- servicesStatus.add(toServiceStatus(s));
- }
- }
-
- String res = gson.toJson(servicesStatus);
- return new ResponseEntity<>(res, HttpStatus.OK);
- }
-
- private ServiceStatus toServiceStatus(Service s) {
- return new ServiceStatus(s.getName(), s.getKeepAliveInterval().toSeconds(), s.timeSinceLastPing().toSeconds(),
- s.getCallbackUrl());
- }
-
- private void validateRegistrationInfo(ServiceRegistrationInfo registrationInfo)
- throws ServiceException, MalformedURLException {
- if (registrationInfo.serviceName.isEmpty()) {
- throw new ServiceException("Missing mandatory parameter 'serviceName'");
- }
- if (registrationInfo.keepAliveIntervalSeconds < 0) {
- throw new ServiceException("Keepalive interval shoul be greater or equal to 0");
- }
- if (!registrationInfo.callbackUrl.isEmpty()) {
- new URL(registrationInfo.callbackUrl);
- }
- }
-
- @ApiOperation(value = "Register a service")
- @ApiResponses(
- value = { //
- @ApiResponse(code = 200, message = "Service updated", response = String.class),
- @ApiResponse(code = 201, message = "Service created", response = String.class), //
- @ApiResponse(code = 400, message = "The ServiceRegistrationInfo is not accepted", response = String.class)})
- @PutMapping("/service")
- public ResponseEntity<String> putService(//
- @RequestBody ServiceRegistrationInfo registrationInfo) {
- try {
- validateRegistrationInfo(registrationInfo);
- final boolean isCreate = this.services.get(registrationInfo.serviceName) == null;
- this.services.put(toService(registrationInfo));
- return new ResponseEntity<>("OK", isCreate ? HttpStatus.CREATED : HttpStatus.OK);
- } catch (Exception e) {
- return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
- }
- }
-
- @ApiOperation(value = "Delete a service")
- @ApiResponses(
- value = { //
- @ApiResponse(code = 204, message = "OK"),
- @ApiResponse(code = 404, message = "Service not found", response = String.class)})
- @DeleteMapping("/services")
- public ResponseEntity<String> deleteService(//
- @ApiParam(name = "name", required = true, value = "The name of the service") //
- @RequestParam(name = "name", required = true) String serviceName) {
- try {
- Service service = removeService(serviceName);
- // Remove the policies from the repo and let the consistency monitoring
- // do the rest.
- removePolicies(service);
- return new ResponseEntity<>("OK", HttpStatus.NO_CONTENT);
- } catch (Exception e) {
- return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
- }
- }
-
- @ApiOperation(value = "Heartbeat from a serice")
- @ApiResponses(
- value = { //
- @ApiResponse(code = 200, message = "Service supervision timer refreshed, OK"),
- @ApiResponse(code = 404, message = "The service is not found, needs re-registration")})
- @PutMapping("/services/keepalive")
- public ResponseEntity<String> keepAliveService(//
- @ApiParam(name = "name", required = true, value = "The name of the service") //
- @RequestParam(name = "name", required = true) String serviceName) {
- try {
- services.getService(serviceName).keepAlive();
- return new ResponseEntity<>("OK", HttpStatus.OK);
- } catch (ServiceException e) {
- return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
- }
- }
-
- private Service removeService(String name) throws ServiceException {
- Service service = this.services.getService(name); // Just to verify that it exists
- this.services.remove(service.getName());
- return service;
- }
-
- private void removePolicies(Service service) {
- Collection<Policy> policyList = this.policies.getForService(service.getName());
- for (Policy policy : policyList) {
- this.policies.remove(policy);
- }
- }
-
- private Service toService(ServiceRegistrationInfo s) {
- return new Service(s.serviceName, Duration.ofSeconds(s.keepAliveIntervalSeconds), s.callbackUrl);
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.controllers;
-
-import com.google.gson.annotations.SerializedName;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-import org.immutables.gson.Gson;
-
-@Gson.TypeAdapters
-@ApiModel(value = "ServiceRegistrationInfo")
-public class ServiceRegistrationInfo {
-
- @ApiModelProperty(value = "identity of the service", required = true, allowEmptyValue = false)
- @SerializedName(value = "serviceName", alternate = {"name"})
-
- public String serviceName = "";
-
- @ApiModelProperty(
- value = "keep alive interval for the service. This is a heartbeat supervision of the service, "
- + "which in regular intevals must invoke a 'keepAlive' REST call. "
- + "When a service does not invoke this call within the given time, it is considered unavailble. "
- + "An unavailable service will be automatically deregistered and its policies will be deleted. "
- + "Value 0 means no timeout supervision.")
- @SerializedName("keepAliveIntervalSeconds")
- public long keepAliveIntervalSeconds = 0;
-
- @ApiModelProperty(value = "callback for notifying of RIC synchronization", required = false, allowEmptyValue = true)
- @SerializedName("callbackUrl")
- public String callbackUrl = "";
-
- public ServiceRegistrationInfo() {
- }
-
- public ServiceRegistrationInfo(String name, long keepAliveIntervalSeconds, String callbackUrl) {
- this.serviceName = name;
- this.keepAliveIntervalSeconds = keepAliveIntervalSeconds;
- this.callbackUrl = callbackUrl;
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.controllers;
-
-import io.swagger.annotations.ApiModel;
-import io.swagger.annotations.ApiModelProperty;
-
-import org.immutables.gson.Gson;
-
-@Gson.TypeAdapters
-@ApiModel(value = "ServiceStatus")
-public class ServiceStatus {
-
- @ApiModelProperty(value = "identity of the service")
- public final String serviceName;
-
- @ApiModelProperty(value = "policy keep alive timeout")
- public final long keepAliveIntervalSeconds;
-
- @ApiModelProperty(value = "time since last invocation by the service")
- public final long timeSinceLastActivitySeconds;
-
- @ApiModelProperty(value = "callback for notifying of RIC synchronization")
- public String callbackUrl;
-
- ServiceStatus(String name, long keepAliveIntervalSeconds, long timeSincePingSeconds, String callbackUrl) {
- this.serviceName = name;
- this.keepAliveIntervalSeconds = keepAliveIntervalSeconds;
- this.timeSinceLastActivitySeconds = timeSincePingSeconds;
- this.callbackUrl = callbackUrl;
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.controllers;
-
-import io.swagger.annotations.Api;
-import io.swagger.annotations.ApiOperation;
-import io.swagger.annotations.ApiResponse;
-import io.swagger.annotations.ApiResponses;
-
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.bind.annotation.GetMapping;
-import org.springframework.web.bind.annotation.RestController;
-import reactor.core.publisher.Mono;
-
-@RestController
-@Api(tags = "Health check")
-public class StatusController {
-
- @GetMapping("/status")
- @ApiOperation(value = "Returns status and statistics of this service")
- @ApiResponses(
- value = { //
- @ApiResponse(code = 200, message = "Service is living", response = String.class) //
- })
- public Mono<ResponseEntity<String>> getStatus() {
- return Mono.just(new ResponseEntity<>("hunky dory", HttpStatus.OK));
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.dmaap;
-
-import com.google.common.collect.Iterables;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParser;
-
-import java.time.Duration;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.oransc.policyagent.clients.AsyncRestClient;
-import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.http.ResponseEntity;
-import org.springframework.stereotype.Component;
-
-/**
- * The class fetches incoming requests from DMAAP. It uses the timeout parameter
- * that lets the MessageRouter keep the connection with the Kafka open until
- * requests are sent in.
- *
- * <p>
- * this service will regularly check the configuration and start polling DMaaP
- * if the configuration is added. If the DMaaP configuration is removed, then
- * the service will stop polling and resume checking for configuration.
- *
- * <p>
- * Each received request is processed by {@link DmaapMessageHandler}.
- */
-@Component
-public class DmaapMessageConsumer {
-
- protected static final Duration TIME_BETWEEN_DMAAP_RETRIES = Duration.ofSeconds(10);
-
- private static final Logger logger = LoggerFactory.getLogger(DmaapMessageConsumer.class);
-
- private final ApplicationConfig applicationConfig;
-
- private DmaapMessageHandler dmaapMessageHandler = null;
-
- @Value("${server.http-port}")
- private int localServerHttpPort;
-
- @Autowired
- public DmaapMessageConsumer(ApplicationConfig applicationConfig) {
- this.applicationConfig = applicationConfig;
- }
-
- /**
- * Starts the consumer. If there is a DMaaP configuration, it will start polling
- * for messages. Otherwise it will check regularly for the configuration.
- *
- * @return the running thread, for test purposes.
- */
- public Thread start() {
- Thread thread = new Thread(this::messageHandlingLoop);
- thread.start();
- return thread;
- }
-
- private void messageHandlingLoop() {
- while (!isStopped()) {
- try {
- if (isDmaapConfigured()) {
- Iterable<String> dmaapMsgs = fetchAllMessages();
- if (dmaapMsgs != null && Iterables.size(dmaapMsgs) > 0) {
- logger.debug("Fetched all the messages from DMAAP and will start to process the messages");
- for (String msg : dmaapMsgs) {
- processMsg(msg);
- }
- }
- } else {
- sleep(TIME_BETWEEN_DMAAP_RETRIES); // wait for configuration
- }
- } catch (Exception e) {
- logger.warn("{}", e.getMessage());
- sleep(TIME_BETWEEN_DMAAP_RETRIES);
- }
- }
- }
-
- protected boolean isStopped() {
- return false;
- }
-
- protected boolean isDmaapConfigured() {
- String producerTopicUrl = applicationConfig.getDmaapProducerTopicUrl();
- String consumerTopicUrl = applicationConfig.getDmaapConsumerTopicUrl();
- return (!producerTopicUrl.isEmpty() && !consumerTopicUrl.isEmpty());
- }
-
- private static List<String> parseMessages(String jsonString) {
- JsonArray arrayOfMessages = JsonParser.parseString(jsonString).getAsJsonArray();
- List<String> result = new ArrayList<>();
- for (JsonElement element : arrayOfMessages) {
- if (element.isJsonPrimitive()) {
- result.add(element.getAsString());
- } else {
- String messageAsString = element.toString();
- result.add(messageAsString);
- }
- }
- return result;
- }
-
- protected Iterable<String> fetchAllMessages() throws ServiceException {
- String topicUrl = this.applicationConfig.getDmaapConsumerTopicUrl();
- AsyncRestClient consumer = getMessageRouterConsumer();
- ResponseEntity<String> response = consumer.getForEntity(topicUrl).block();
- logger.debug("DMaaP consumer received {} : {}", response.getStatusCode(), response.getBody());
- if (response.getStatusCode().is2xxSuccessful()) {
- return parseMessages(response.getBody());
- } else {
- throw new ServiceException("Cannot fetch because of Error respons: " + response.getStatusCode().toString()
- + " " + response.getBody());
- }
- }
-
- private void processMsg(String msg) {
- logger.debug("Message Reveived from DMAAP : {}", msg);
- getDmaapMessageHandler().handleDmaapMsg(msg);
- }
-
- protected DmaapMessageHandler getDmaapMessageHandler() {
- if (this.dmaapMessageHandler == null) {
- String agentBaseUrl = "http://localhost:" + this.localServerHttpPort;
- AsyncRestClient agentClient =
- new AsyncRestClient(agentBaseUrl, this.applicationConfig.getWebClientConfig());
- AsyncRestClient producer = new AsyncRestClient(this.applicationConfig.getDmaapProducerTopicUrl(),
- this.applicationConfig.getWebClientConfig());
- this.dmaapMessageHandler = new DmaapMessageHandler(producer, agentClient);
- }
- return this.dmaapMessageHandler;
- }
-
- protected void sleep(Duration duration) {
- try {
- Thread.sleep(duration.toMillis());
- } catch (Exception e) {
- logger.error("Failed to put the thread to sleep", e);
- }
- }
-
- protected AsyncRestClient getMessageRouterConsumer() {
- return new AsyncRestClient("", this.applicationConfig.getWebClientConfig());
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.dmaap;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonObject;
-
-import java.util.Optional;
-
-import org.oransc.policyagent.clients.AsyncRestClient;
-import org.oransc.policyagent.dmaap.DmaapRequestMessage.Operation;
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.reactive.function.client.WebClientException;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-import reactor.core.publisher.Mono;
-
-/**
- * The class handles incoming requests from DMAAP.
- * <p>
- * That means: invoke a REST call towards this services and to send back a response though DMAAP
- */
-public class DmaapMessageHandler {
- private static final Logger logger = LoggerFactory.getLogger(DmaapMessageHandler.class);
- private static Gson gson = new GsonBuilder() //
- .create(); //
- private final AsyncRestClient dmaapClient;
- private final AsyncRestClient agentClient;
-
- public DmaapMessageHandler(AsyncRestClient dmaapClient, AsyncRestClient agentClient) {
- this.agentClient = agentClient;
- this.dmaapClient = dmaapClient;
- }
-
- public void handleDmaapMsg(String msg) {
- try {
- String result = this.createTask(msg).block();
- logger.debug("handleDmaapMsg: {}", result);
- } catch (Exception throwable) {
- logger.warn("handleDmaapMsg failure {}", throwable.getMessage());
- }
- }
-
- Mono<String> createTask(String msg) {
- try {
- DmaapRequestMessage dmaapRequestMessage = gson.fromJson(msg, ImmutableDmaapRequestMessage.class);
- return this.invokePolicyAgent(dmaapRequestMessage) //
- .onErrorResume(t -> handleAgentCallError(t, dmaapRequestMessage)) //
- .flatMap(
- response -> sendDmaapResponse(response.getBody(), dmaapRequestMessage, response.getStatusCode()));
- } catch (Exception e) {
- String errorMsg = "Received unparsable message from DMAAP: \"" + msg + "\", reason: " + e.getMessage();
- return Mono.error(new ServiceException(errorMsg)); // Cannot make any response
- }
- }
-
- private Mono<ResponseEntity<String>> handleAgentCallError(Throwable error,
- DmaapRequestMessage dmaapRequestMessage) {
- logger.debug("Agent call failed: {}", error.getMessage());
- HttpStatus status = HttpStatus.INTERNAL_SERVER_ERROR;
- String errorMessage = error.getMessage();
- if (error instanceof WebClientResponseException) {
- WebClientResponseException exception = (WebClientResponseException) error;
- status = exception.getStatusCode();
- errorMessage = exception.getResponseBodyAsString();
- } else if (error instanceof ServiceException) {
- status = HttpStatus.BAD_REQUEST;
- errorMessage = error.getMessage();
- } else if (!(error instanceof WebClientException)) {
- logger.warn("Unexpected exception ", error);
- }
- return sendDmaapResponse(errorMessage, dmaapRequestMessage, status) //
- .flatMap(notUsed -> Mono.empty());
- }
-
- private Mono<ResponseEntity<String>> invokePolicyAgent(DmaapRequestMessage dmaapRequestMessage) {
- DmaapRequestMessage.Operation operation = dmaapRequestMessage.operation();
- String uri = dmaapRequestMessage.url();
-
- if (operation == Operation.DELETE) {
- return agentClient.deleteForEntity(uri);
- } else if (operation == Operation.GET) {
- return agentClient.getForEntity(uri);
- } else if (operation == Operation.PUT) {
- return agentClient.putForEntity(uri, payload(dmaapRequestMessage));
- } else if (operation == Operation.POST) {
- return agentClient.postForEntity(uri, payload(dmaapRequestMessage));
- } else {
- return Mono.error(new ServiceException("Not implemented operation: " + operation));
- }
- }
-
- private String payload(DmaapRequestMessage message) {
- Optional<JsonObject> payload = message.payload();
- if (payload.isPresent()) {
- return gson.toJson(payload.get());
- } else {
- logger.warn("Expected payload in message from DMAAP: {}", message);
- return "";
- }
- }
-
- private Mono<String> sendDmaapResponse(String response, DmaapRequestMessage dmaapRequestMessage,
- HttpStatus status) {
- return createDmaapResponseMessage(dmaapRequestMessage, response, status) //
- .flatMap(this::sendToDmaap) //
- .onErrorResume(this::handleResponseCallError);
- }
-
- private Mono<String> sendToDmaap(String body) {
- logger.debug("sendToDmaap: {} ", body);
- return dmaapClient.post("", "[" + body + "]");
- }
-
- private Mono<String> handleResponseCallError(Throwable t) {
- logger.debug("Failed to send response to DMaaP: {}", t.getMessage());
- return Mono.empty();
- }
-
- private Mono<String> createDmaapResponseMessage(DmaapRequestMessage dmaapRequestMessage, String response,
- HttpStatus status) {
- DmaapResponseMessage dmaapResponseMessage = ImmutableDmaapResponseMessage.builder() //
- .status(status.toString()) //
- .message(response == null ? "" : response) //
- .type("response") //
- .correlationId(dmaapRequestMessage.correlationId() == null ? "" : dmaapRequestMessage.correlationId()) //
- .originatorId(dmaapRequestMessage.originatorId() == null ? "" : dmaapRequestMessage.originatorId()) //
- .requestId(dmaapRequestMessage.requestId() == null ? "" : dmaapRequestMessage.requestId()) //
- .timestamp(dmaapRequestMessage.timestamp() == null ? "" : dmaapRequestMessage.timestamp()) //
- .build();
- String str = gson.toJson(dmaapResponseMessage);
- return Mono.just(str);
-
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.dmaap;
-
-import com.google.gson.JsonObject;
-
-import java.util.Optional;
-
-import org.immutables.gson.Gson;
-import org.immutables.value.Value;
-
-@Value.Immutable
-@Gson.TypeAdapters
-public interface DmaapRequestMessage {
-
- public enum Operation {
- PUT, GET, DELETE, POST
- }
-
- String correlationId();
-
- String target();
-
- String timestamp();
-
- String apiVersion();
-
- String originatorId();
-
- String requestId();
-
- Operation operation();
-
- String url();
-
- Optional<JsonObject> payload();
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.dmaap;
-
-import org.immutables.gson.Gson;
-import org.immutables.value.Value;
-
-@Value.Immutable
-@Gson.TypeAdapters
-public interface DmaapResponseMessage {
-
- String type();
-
- String correlationId();
-
- String timestamp();
-
- String originatorId();
-
- String requestId();
-
- String status();
-
- String message();
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.exceptions;
-
-public class EnvironmentLoaderException extends ServiceException {
-
- private static final long serialVersionUID = 1L;
-
- public EnvironmentLoaderException(String message) {
- super(message);
- }
-}
+++ /dev/null
-/*-
- * ============LICENSE_START======================================================================
- * Copyright (C) 2019 Nordix Foundation. All rights reserved.
- * ===============================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ============LICENSE_END========================================================================
- */
-
-package org.oransc.policyagent.exceptions;
-
-public class ServiceException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- public ServiceException(String message) {
- super(message);
- }
-
- public ServiceException(String message, Exception originalException) {
- super(message, originalException);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.repository;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import reactor.core.publisher.Mono;
-import reactor.core.publisher.MonoSink;
-
-/**
- * A resource lock. Exclusive means that the caller takes exclusive ownership of
- * the resurce. Non exclusive lock means that several users can lock the
- * resource (for shared usage).
- */
-public class Lock {
- private static final Logger logger = LoggerFactory.getLogger(Lock.class);
-
- private boolean isExclusive = false;
- private int lockCounter = 0;
- private final List<LockRequest> lockRequestQueue = new LinkedList<>();
- private static AsynchCallbackExecutor callbackProcessor = new AsynchCallbackExecutor();
-
- public enum LockType {
- EXCLUSIVE, SHARED
- }
-
- /** The caller thread will be blocked util the lock is granted. */
- public synchronized void lockBlocking(LockType locktype) {
- while (!tryLock(locktype)) {
- this.waitForUnlock();
- }
- }
-
- /** Reactive version. The Lock will be emitted when the lock is granted */
- public synchronized Mono<Lock> lock(LockType lockType) {
- if (tryLock(lockType)) {
- return Mono.just(this);
- } else {
- return Mono.create(monoSink -> addToQueue(monoSink, lockType));
- }
- }
-
- public Mono<Lock> unlock() {
- return Mono.create(monoSink -> {
- unlockBlocking();
- monoSink.success(this);
- });
- }
-
- public synchronized void unlockBlocking() {
- if (lockCounter <= 0) {
- lockCounter = -1; // Might as well stop, to make it easier to find the problem
- logger.error("Number of unlocks must match the number of locks");
- }
- this.lockCounter--;
- if (lockCounter == 0) {
- isExclusive = false;
- }
- this.notifyAll();
- this.processQueuedEntries();
- }
-
- @Override
- public synchronized String toString() {
- return "Lock cnt: " + this.lockCounter + " exclusive: " + this.isExclusive + " queued: "
- + this.lockRequestQueue.size();
- }
-
- /** returns the current number of granted locks */
- public synchronized int getLockCounter() {
- return this.lockCounter;
- }
-
- private void processQueuedEntries() {
- List<LockRequest> granted = new ArrayList<>();
- for (Iterator<LockRequest> i = lockRequestQueue.iterator(); i.hasNext();) {
- LockRequest request = i.next();
- if (tryLock(request.lockType)) {
- i.remove();
- granted.add(request);
- }
- }
- callbackProcessor.addAll(granted);
- }
-
- private synchronized void addToQueue(MonoSink<Lock> callback, LockType lockType) {
- lockRequestQueue.add(new LockRequest(callback, lockType, this));
- processQueuedEntries();
- }
-
- @SuppressWarnings("java:S2274") // Always invoke wait() and await() methods inside a loop
- private synchronized void waitForUnlock() {
- try {
- this.wait();
- } catch (InterruptedException e) {
- logger.warn("waitForUnlock interrupted", e);
- Thread.currentThread().interrupt();
- }
- }
-
- private boolean tryLock(LockType lockType) {
- if (this.isExclusive) {
- return false;
- }
- if (lockType == LockType.EXCLUSIVE && lockCounter > 0) {
- return false;
- }
- lockCounter++;
- this.isExclusive = lockType == LockType.EXCLUSIVE;
- return true;
- }
-
- /**
- * Represents a queued lock request
- */
- private static class LockRequest {
- final MonoSink<Lock> callback;
- final LockType lockType;
- final Lock lock;
-
- LockRequest(MonoSink<Lock> callback, LockType lockType, Lock lock) {
- this.callback = callback;
- this.lockType = lockType;
- this.lock = lock;
- }
- }
-
- /**
- * A separate thread that calls a MonoSink to continue. This is done after a
- * queued lock is granted.
- */
- private static class AsynchCallbackExecutor implements Runnable {
- private List<LockRequest> lockRequestQueue = new LinkedList<>();
-
- public AsynchCallbackExecutor() {
- Thread thread = new Thread(this);
- thread.start();
- }
-
- public synchronized void addAll(List<LockRequest> requests) {
- this.lockRequestQueue.addAll(requests);
- this.notifyAll();
- }
-
- @Override
- public void run() {
- try {
- while (true) {
- for (LockRequest request : consume()) {
- request.callback.success(request.lock);
- }
- waitForNewEntries();
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- logger.error("Interrupted {}", e.getMessage());
- }
- }
-
- private synchronized List<LockRequest> consume() {
- List<LockRequest> q = this.lockRequestQueue;
- this.lockRequestQueue = new LinkedList<>();
- return q;
- }
-
- @SuppressWarnings("java:S2274")
- private synchronized void waitForNewEntries() throws InterruptedException {
- if (this.lockRequestQueue.isEmpty()) {
- this.wait();
- }
- }
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.repository;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import java.util.Vector;
-
-import org.oransc.policyagent.exceptions.ServiceException;
-
-public class Policies {
- private Map<String, Policy> policiesId = new HashMap<>();
- private Map<String, Map<String, Policy>> policiesRic = new HashMap<>();
- private Map<String, Map<String, Policy>> policiesService = new HashMap<>();
- private Map<String, Map<String, Policy>> policiesType = new HashMap<>();
-
- public synchronized void put(Policy policy) {
- policiesId.put(policy.id(), policy);
- multiMapPut(policiesRic, policy.ric().name(), policy);
- multiMapPut(policiesService, policy.ownerServiceName(), policy);
- multiMapPut(policiesType, policy.type().name(), policy);
- }
-
- private void multiMapPut(Map<String, Map<String, Policy>> multiMap, String key, Policy value) {
- multiMap.computeIfAbsent(key, k -> new HashMap<>()).put(value.id(), value);
- }
-
- private void multiMapRemove(Map<String, Map<String, Policy>> multiMap, String key, Policy value) {
- Map<String, Policy> map = multiMap.get(key);
- if (map != null) {
- map.remove(value.id());
- if (map.isEmpty()) {
- multiMap.remove(key);
- }
- }
- }
-
- private Collection<Policy> multiMapGet(Map<String, Map<String, Policy>> multiMap, String key) {
- Map<String, Policy> map = multiMap.get(key);
- if (map == null) {
- return Collections.emptyList();
- }
- return new Vector<>(map.values());
- }
-
- public synchronized boolean containsPolicy(String id) {
- return policiesId.containsKey(id);
- }
-
- public synchronized Policy get(String id) {
- return policiesId.get(id);
- }
-
- public synchronized Policy getPolicy(String id) throws ServiceException {
- Policy p = policiesId.get(id);
- if (p == null) {
- throw new ServiceException("Could not find policy: " + id);
- }
- return p;
- }
-
- public synchronized Collection<Policy> getAll() {
- return new Vector<>(policiesId.values());
- }
-
- public synchronized Collection<Policy> getForService(String service) {
- return multiMapGet(policiesService, service);
- }
-
- public synchronized Collection<Policy> getForRic(String ric) {
- return multiMapGet(policiesRic, ric);
- }
-
- public synchronized Collection<Policy> getForType(String type) {
- return multiMapGet(policiesType, type);
- }
-
- public synchronized Policy removeId(String id) {
- Policy p = policiesId.get(id);
- if (p != null) {
- remove(p);
- }
- return p;
- }
-
- public synchronized void remove(Policy policy) {
- policiesId.remove(policy.id());
- multiMapRemove(policiesRic, policy.ric().name(), policy);
- multiMapRemove(policiesService, policy.ownerServiceName(), policy);
- multiMapRemove(policiesType, policy.type().name(), policy);
- }
-
- public synchronized void removePoliciesForRic(String ricName) {
- Collection<Policy> policiesForRic = getForRic(ricName);
- for (Policy policy : policiesForRic) {
- remove(policy);
- }
- }
-
- public synchronized int size() {
- return policiesId.size();
- }
-
- public synchronized void clear() {
- while (policiesId.size() > 0) {
- Set<String> keys = policiesId.keySet();
- removeId(keys.iterator().next());
- }
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.repository;
-
-import org.immutables.gson.Gson;
-import org.immutables.value.Value;
-
-@Value.Immutable
-@Gson.TypeAdapters
-public interface Policy {
- public String id();
-
- public String json();
-
- public String ownerServiceName();
-
- public Ric ric();
-
- public PolicyType type();
-
- public String lastModified();
-
- public boolean isTransient();
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.repository;
-
-import org.immutables.gson.Gson;
-import org.immutables.value.Value;
-
-@Value.Immutable
-@Gson.TypeAdapters
-public interface PolicyType {
- public String name();
-
- public String schema();
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.repository;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Vector;
-
-import org.oransc.policyagent.exceptions.ServiceException;
-
-public class PolicyTypes {
- private Map<String, PolicyType> types = new HashMap<>();
-
- public synchronized PolicyType getType(String name) throws ServiceException {
- PolicyType t = types.get(name);
- if (t == null) {
- throw new ServiceException("Could not find type: " + name);
- }
- return t;
- }
-
- public synchronized PolicyType get(String name) {
- return types.get(name);
- }
-
- public synchronized void put(PolicyType type) {
- types.put(type.name(), type);
- }
-
- public synchronized boolean contains(String policyType) {
- return types.containsKey(policyType);
- }
-
- public synchronized Collection<PolicyType> getAll() {
- return new Vector<>(types.values());
- }
-
- public synchronized int size() {
- return types.size();
- }
-
- public synchronized void clear() {
- this.types.clear();
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.repository;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Vector;
-
-import lombok.Getter;
-import lombok.Setter;
-
-import org.oransc.policyagent.clients.A1Client.A1ProtocolType;
-import org.oransc.policyagent.configuration.RicConfig;
-
-/**
- * Represents the dynamic information about a Near-RT RIC.
- */
-public class Ric {
-
- @Setter
- private RicConfig ricConfig;
- private RicState state = RicState.UNAVAILABLE;
- private Map<String, PolicyType> supportedPolicyTypes = new HashMap<>();
- @Getter
- @Setter
- private A1ProtocolType protocolVersion = A1ProtocolType.UNKNOWN;
-
- @Getter
- private final Lock lock = new Lock();
-
- /**
- * Creates the Ric. Initial state is {@link RicState.UNDEFINED}.
- *
- * @param ricConfig The {@link RicConfig} for this Ric.
- */
- public Ric(RicConfig ricConfig) {
- this.ricConfig = ricConfig;
- }
-
- public String name() {
- return ricConfig.name();
- }
-
- public RicConfig getConfig() {
- return this.ricConfig;
- }
-
- public synchronized RicState getState() {
- return this.state;
- }
-
- public synchronized void setState(RicState state) {
- this.state = state;
- }
-
- /**
- * Gets the nodes managed by this Ric.
- *
- * @return a vector containing the nodes managed by this Ric.
- */
- public synchronized Collection<String> getManagedElementIds() {
- return ricConfig.managedElementIds();
- }
-
- /**
- * Determines if the given node is managed by this Ric.
- *
- * @param managedElementId the node name to check.
- * @return true if the given node is managed by this Ric.
- */
- public synchronized boolean isManaging(String managedElementId) {
- return ricConfig.managedElementIds().contains(managedElementId);
- }
-
- /**
- * Gets the policy types supported by this Ric.
- *
- * @return the policy types supported by this Ric in an unmodifiable list.
- */
- public synchronized Collection<PolicyType> getSupportedPolicyTypes() {
- return new Vector<>(supportedPolicyTypes.values());
- }
-
- public synchronized Collection<String> getSupportedPolicyTypeNames() {
- return new Vector<>(supportedPolicyTypes.keySet());
- }
-
- /**
- * Adds a policy type as supported by this Ric.
- *
- * @param type the policy type to support.
- */
- public synchronized void addSupportedPolicyType(PolicyType type) {
- supportedPolicyTypes.put(type.name(), type);
- }
-
- /**
- * Removes all policy type as supported by this Ric.
- */
- public synchronized void clearSupportedPolicyTypes() {
- supportedPolicyTypes.clear();
- }
-
- /**
- * Checks if a type is supported by this Ric.
- *
- * @param typeName the name of the type to check if it is supported.
- *
- * @return true if the given type is supported by this Ric, false otherwise.
- */
- public synchronized boolean isSupportingType(String typeName) {
- return supportedPolicyTypes.containsKey(typeName);
- }
-
- @Override
- public synchronized String toString() {
- return Ric.class.getSimpleName() + ": " + "name: " + name() + ", state: " + state + ", baseUrl: "
- + ricConfig.baseUrl() + ", managedNodes: " + ricConfig.managedElementIds();
- }
-
- /**
- * Represents the states possible for a Ric.
- */
- public enum RicState {
- /**
- * The agent view of the Ric may be inconsistent.
- */
- UNAVAILABLE,
- /**
- * The normal state. Policies can be configured.
- */
- AVAILABLE,
- /**
- * The agent is synchronizing the view of the Ric.
- */
- SYNCHRONIZING,
-
- /**
- * A consistency check between the agent and the Ric is done
- */
- CONSISTENCY_CHECK
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.repository;
-
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Vector;
-
-import org.oransc.policyagent.exceptions.ServiceException;
-
-/**
- * Dynamic representation of all Rics in the system.
- */
-public class Rics {
- Map<String, Ric> registeredRics = new HashMap<>();
-
- public synchronized void put(Ric ric) {
- registeredRics.put(ric.name(), ric);
- }
-
- public synchronized Collection<Ric> getRics() {
- return new Vector<>(registeredRics.values());
- }
-
- public synchronized Ric getRic(String name) throws ServiceException {
- Ric ric = registeredRics.get(name);
- if (ric == null) {
- throw new ServiceException("Could not find ric: " + name);
- }
- return ric;
- }
-
- public synchronized Ric get(String name) {
- return registeredRics.get(name);
- }
-
- public synchronized void remove(String name) {
- registeredRics.remove(name);
- }
-
- public synchronized int size() {
- return registeredRics.size();
- }
-
- public synchronized void clear() {
- this.registeredRics.clear();
- }
-
- public synchronized Optional<Ric> lookupRicForManagedElement(String managedElementId) {
- for (Ric ric : this.registeredRics.values()) {
- if (ric.getManagedElementIds().contains(managedElementId)) {
- return Optional.of(ric);
- }
- }
- return Optional.empty();
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.repository;
-
-import java.time.Duration;
-import java.time.Instant;
-
-import lombok.Getter;
-
-public class Service {
- @Getter
- private final String name;
- private final Duration keepAliveInterval;
- private Instant lastPing;
- private final String callbackUrl;
-
- public Service(String name, Duration keepAliveInterval, String callbackUrl) {
- this.name = name;
- this.keepAliveInterval = keepAliveInterval;
- this.callbackUrl = callbackUrl;
- keepAlive();
- }
-
- public synchronized Duration getKeepAliveInterval() {
- return this.keepAliveInterval;
- }
-
- public synchronized void keepAlive() {
- this.lastPing = Instant.now();
- }
-
- public synchronized boolean isExpired() {
- return this.keepAliveInterval.getSeconds() > 0 && timeSinceLastPing().compareTo(this.keepAliveInterval) > 0;
- }
-
- public synchronized Duration timeSinceLastPing() {
- return Duration.between(this.lastPing, Instant.now());
- }
-
- public synchronized String getCallbackUrl() {
- return this.callbackUrl;
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.repository;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Vector;
-
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-public class Services {
- private static final Logger logger = LoggerFactory.getLogger(Services.class);
-
- private Map<String, Service> registeredServices = new HashMap<>();
-
- public synchronized Service getService(String name) throws ServiceException {
- Service s = registeredServices.get(name);
- if (s == null) {
- throw new ServiceException("Could not find service: " + name);
- }
- return s;
- }
-
- public synchronized Service get(String name) {
- return registeredServices.get(name);
- }
-
- public synchronized void put(Service service) {
- logger.debug("Put service: {}", service.getName());
- service.keepAlive();
- registeredServices.put(service.getName(), service);
- }
-
- public synchronized Iterable<Service> getAll() {
- return new Vector<>(registeredServices.values());
- }
-
- public synchronized void remove(String name) {
- registeredServices.remove(name);
- }
-
- public synchronized int size() {
- return registeredServices.size();
- }
-
- public synchronized void clear() {
- registeredServices.clear();
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.tasks;
-
-import java.util.Optional;
-import java.util.Properties;
-
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.EnvProperties;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.ImmutableEnvProperties;
-import org.oransc.policyagent.exceptions.EnvironmentLoaderException;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import reactor.core.publisher.Mono;
-
-/**
- * This class reads a few environment variables used for locating the Consul
- * (Config Binding Service).
- */
-class EnvironmentProcessor {
-
- private static final int DEFAULT_CONSUL_PORT = 8500;
- private static final Logger logger = LoggerFactory.getLogger(EnvironmentProcessor.class);
-
- private EnvironmentProcessor() {
- }
-
- static Mono<EnvProperties> readEnvironmentVariables(Properties systemEnvironment) {
-
- EnvProperties envProperties;
- try {
- envProperties = ImmutableEnvProperties.builder() //
- .consulHost(getConsulHost(systemEnvironment)) //
- .consulPort(getConsultPort(systemEnvironment)) //
- .cbsName(getConfigBindingService(systemEnvironment)) //
- .appName(getService(systemEnvironment)) //
- .build();
- } catch (EnvironmentLoaderException e) {
- return Mono.error(e);
- }
- logger.trace("Evaluated environment system variables {}", envProperties);
- return Mono.just(envProperties);
- }
-
- private static String getConsulHost(Properties systemEnvironments) throws EnvironmentLoaderException {
- return Optional.ofNullable(systemEnvironments.getProperty("CONSUL_HOST"))
- .orElseThrow(() -> new EnvironmentLoaderException("$CONSUL_HOST environment has not been defined"));
- }
-
- private static Integer getConsultPort(Properties systemEnvironments) {
- return Optional.ofNullable(systemEnvironments.getProperty("CONSUL_PORT")) //
- .map(Integer::valueOf) //
- .orElseGet(EnvironmentProcessor::getDefaultPortOfConsul);
- }
-
- private static String getConfigBindingService(Properties systemEnvironments) throws EnvironmentLoaderException {
- return Optional.ofNullable(systemEnvironments.getProperty("CONFIG_BINDING_SERVICE")) //
- .orElseThrow(
- () -> new EnvironmentLoaderException("$CONFIG_BINDING_SERVICE environment has not been defined"));
- }
-
- private static String getService(Properties systemEnvironments) throws EnvironmentLoaderException {
- return Optional
- .ofNullable(Optional.ofNullable(systemEnvironments.getProperty("HOSTNAME"))
- .orElse(systemEnvironments.getProperty("SERVICE_NAME")))
- .orElseThrow(() -> new EnvironmentLoaderException(
- "Neither $HOSTNAME/$SERVICE_NAME have not been defined as system environment"));
- }
-
- private static Integer getDefaultPortOfConsul() {
- logger.warn("$CONSUL_PORT variable will be set to default port {}", DEFAULT_CONSUL_PORT);
- return DEFAULT_CONSUL_PORT;
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.tasks;
-
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gson.TypeAdapterFactory;
-
-import java.io.BufferedInputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.time.Duration;
-import java.util.Properties;
-import java.util.ServiceLoader;
-
-import javax.validation.constraints.NotNull;
-
-import lombok.AccessLevel;
-import lombok.Getter;
-
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsClient;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsClientFactory;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsRequests;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.CbsRequest;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.EnvProperties;
-import org.onap.dcaegen2.services.sdk.rest.services.model.logging.RequestDiagnosticContext;
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.configuration.ApplicationConfig.RicConfigUpdate;
-import org.oransc.policyagent.configuration.ApplicationConfigParser;
-import org.oransc.policyagent.configuration.RicConfig;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Rics;
-import org.oransc.policyagent.repository.Services;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.stereotype.Component;
-
-import reactor.core.Disposable;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-/**
- * Regularly refreshes the configuration from Consul or from a local configuration file.
- */
-@Component
-public class RefreshConfigTask {
-
- private static final Logger logger = LoggerFactory.getLogger(RefreshConfigTask.class);
-
- @Value("#{systemEnvironment}")
- public Properties systemEnvironment;
-
- /**
- * The time between refreshes of the configuration.
- */
- static final Duration CONFIG_REFRESH_INTERVAL = Duration.ofMinutes(1);
-
- final ApplicationConfig appConfig;
- @Getter(AccessLevel.PROTECTED)
- private Disposable refreshTask = null;
- private boolean isConsulUsed = false;
-
- private final Rics rics;
- private final A1ClientFactory a1ClientFactory;
- private final Policies policies;
- private final Services services;
- private final PolicyTypes policyTypes;
-
- @Autowired
- public RefreshConfigTask(ApplicationConfig appConfig, Rics rics, Policies policies, Services services,
- PolicyTypes policyTypes, A1ClientFactory a1ClientFactory) {
- this.appConfig = appConfig;
- this.rics = rics;
- this.policies = policies;
- this.services = services;
- this.policyTypes = policyTypes;
- this.a1ClientFactory = a1ClientFactory;
- }
-
- public void start() {
- logger.debug("Starting refreshConfigTask");
- stop();
- refreshTask = createRefreshTask() //
- .subscribe(notUsed -> logger.debug("Refreshed configuration data"),
- throwable -> logger.error("Configuration refresh terminated due to exception {}", throwable.toString()),
- () -> logger.error("Configuration refresh terminated"));
- }
-
- public void stop() {
- if (refreshTask != null) {
- refreshTask.dispose();
- }
- }
-
- Flux<RicConfigUpdate.Type> createRefreshTask() {
- Flux<JsonObject> loadFromFile = Flux.interval(Duration.ZERO, CONFIG_REFRESH_INTERVAL) //
- .filter(notUsed -> !this.isConsulUsed) //
- .flatMap(notUsed -> loadConfigurationFromFile()) //
- .onErrorResume(this::ignoreErrorFlux) //
- .doOnNext(json -> logger.debug("loadFromFile succeeded")) //
- .doOnTerminate(() -> logger.error("loadFromFile Terminate"));
-
- Flux<JsonObject> loadFromConsul = Flux.interval(Duration.ZERO, CONFIG_REFRESH_INTERVAL) //
- .flatMap(i -> getEnvironment(systemEnvironment)) //
- .flatMap(this::createCbsClient) //
- .flatMap(this::getFromCbs) //
- .onErrorResume(this::ignoreErrorMono) //
- .doOnNext(json -> logger.debug("loadFromConsul succeeded")) //
- .doOnNext(json -> this.isConsulUsed = true) //
- .doOnTerminate(() -> logger.error("loadFromConsul Terminated"));
-
- return Flux.merge(loadFromFile, loadFromConsul) //
- .flatMap(this::parseConfiguration) //
- .flatMap(this::updateConfig) //
- .doOnNext(this::handleUpdatedRicConfig) //
- .flatMap(configUpdate -> Flux.just(configUpdate.getType())) //
- .doOnTerminate(() -> logger.error("Configuration refresh task is terminated"));
- }
-
- Mono<EnvProperties> getEnvironment(Properties systemEnvironment) {
- return EnvironmentProcessor.readEnvironmentVariables(systemEnvironment) //
- .onErrorResume(t -> Mono.empty());
- }
-
- Mono<CbsClient> createCbsClient(EnvProperties env) {
- return CbsClientFactory.createCbsClient(env) //
- .onErrorResume(this::ignoreErrorMono);
- }
-
- private Mono<JsonObject> getFromCbs(CbsClient cbsClient) {
- try {
- final CbsRequest getConfigRequest = CbsRequests.getAll(RequestDiagnosticContext.create());
- return cbsClient.get(getConfigRequest) //
- .onErrorResume(this::ignoreErrorMono);
- } catch (Exception e) {
- return ignoreErrorMono(e);
- }
- }
-
- private <R> Flux<R> ignoreErrorFlux(Throwable throwable) {
- String errMsg = throwable.toString();
- logger.warn("Could not refresh application configuration. {}", errMsg);
- return Flux.empty();
- }
-
- private <R> Mono<R> ignoreErrorMono(Throwable throwable) {
- String errMsg = throwable.toString();
- logger.warn("Could not refresh application configuration. {}", errMsg);
- return Mono.empty();
- }
-
- private Mono<ApplicationConfigParser.ConfigParserResult> parseConfiguration(JsonObject jsonObject) {
- try {
- ApplicationConfigParser parser = new ApplicationConfigParser();
- return Mono.just(parser.parse(jsonObject));
- } catch (Exception e) {
- String str = e.toString();
- logger.error("Could not parse configuration {}", str);
- return Mono.empty();
- }
- }
-
- private Flux<RicConfigUpdate> updateConfig(ApplicationConfigParser.ConfigParserResult config) {
- return this.appConfig.setConfiguration(config);
- }
-
- boolean fileExists(String filepath) {
- return (filepath != null && (new File(filepath).exists()));
- }
-
- private void handleUpdatedRicConfig(RicConfigUpdate updatedInfo) {
- synchronized (this.rics) {
- String ricName = updatedInfo.getRicConfig().name();
- RicConfigUpdate.Type event = updatedInfo.getType();
- if (event == RicConfigUpdate.Type.ADDED) {
- addRic(updatedInfo.getRicConfig());
- } else if (event == RicConfigUpdate.Type.REMOVED) {
- rics.remove(ricName);
- this.policies.removePoliciesForRic(ricName);
- } else if (event == RicConfigUpdate.Type.CHANGED) {
- Ric ric = this.rics.get(ricName);
- if (ric == null) {
- // Should not happen,just for robustness
- addRic(updatedInfo.getRicConfig());
- } else {
- ric.setRicConfig(updatedInfo.getRicConfig());
- }
- }
- }
- }
-
- private void addRic(RicConfig config) {
- Ric ric = new Ric(config);
- this.rics.put(ric);
- runRicSynchronization(ric);
- }
-
- void runRicSynchronization(Ric ric) {
- RicSynchronizationTask synchronizationTask =
- new RicSynchronizationTask(a1ClientFactory, policyTypes, policies, services);
- synchronizationTask.run(ric);
- }
-
- /**
- * Reads the configuration from file.
- */
- Flux<JsonObject> loadConfigurationFromFile() {
- String filepath = appConfig.getLocalConfigurationFilePath();
- if (!fileExists(filepath)) {
- return Flux.empty();
- }
-
- GsonBuilder gsonBuilder = new GsonBuilder();
- ServiceLoader.load(TypeAdapterFactory.class).forEach(gsonBuilder::registerTypeAdapterFactory);
-
- try (InputStream inputStream = createInputStream(filepath)) {
- JsonObject rootObject = getJsonElement(inputStream).getAsJsonObject();
- ApplicationConfigParser appParser = new ApplicationConfigParser();
- appParser.parse(rootObject);
- logger.debug("Local configuration file loaded: {}", filepath);
- return Flux.just(rootObject);
- } catch (Exception e) {
- logger.error("Local configuration file not loaded: {}, {}", filepath, e.getMessage());
- return Flux.empty();
- }
- }
-
- JsonElement getJsonElement(InputStream inputStream) {
- return JsonParser.parseReader(new InputStreamReader(inputStream));
- }
-
- InputStream createInputStream(@NotNull String filepath) throws IOException {
- return new BufferedInputStream(new FileInputStream(filepath));
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.tasks;
-
-import java.util.Collection;
-
-import org.oransc.policyagent.clients.A1Client;
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.oransc.policyagent.repository.Lock.LockType;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Ric.RicState;
-import org.oransc.policyagent.repository.Rics;
-import org.oransc.policyagent.repository.Services;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.scheduling.annotation.Scheduled;
-import org.springframework.stereotype.Component;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-/**
- * Regularly checks the existing rics towards the local repository to keep it
- * consistent. When the policy types or instances in the Near-RT RIC is not
- * consistent, a synchronization is performed.
- */
-@Component
-@EnableScheduling
-@SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally
-public class RicSupervision {
- private static final Logger logger = LoggerFactory.getLogger(RicSupervision.class);
-
- private final Rics rics;
- private final Policies policies;
- private final PolicyTypes policyTypes;
- private final A1ClientFactory a1ClientFactory;
- private final Services services;
-
- private static class SynchStartedException extends ServiceException {
- private static final long serialVersionUID = 1L;
-
- public SynchStartedException(String message) {
- super(message);
- }
- }
-
- private static class RicData {
- RicData(Ric ric, A1Client a1Client) {
- this.ric = ric;
- this.a1Client = a1Client;
- }
-
- A1Client getClient() {
- return a1Client;
- }
-
- final Ric ric;
- private final A1Client a1Client;
- }
-
- @Autowired
- public RicSupervision(Rics rics, Policies policies, A1ClientFactory a1ClientFactory, PolicyTypes policyTypes,
- Services services) {
- this.rics = rics;
- this.policies = policies;
- this.a1ClientFactory = a1ClientFactory;
- this.policyTypes = policyTypes;
- this.services = services;
- }
-
- /**
- * Regularly contacts all Rics to check if they are alive and synchronized.
- */
- @Scheduled(fixedRate = 1000 * 60)
- public void checkAllRics() {
- logger.debug("Checking Rics starting");
- createTask().subscribe(null, null, () -> logger.debug("Checking all RICs completed"));
- }
-
- private Flux<RicData> createTask() {
- return Flux.fromIterable(rics.getRics()) //
- .flatMap(this::createRicData) //
- .flatMap(this::checkOneRic);
- }
-
- private Mono<RicData> checkOneRic(RicData ricData) {
- return checkRicState(ricData) //
- .flatMap(x -> ricData.ric.getLock().lock(LockType.EXCLUSIVE)) //
- .flatMap(notUsed -> setRicState(ricData)) //
- .flatMap(x -> checkRicPolicies(ricData)) //
- .flatMap(x -> checkRicPolicyTypes(ricData)) //
- .doOnNext(x -> onRicCheckedOk(ricData)) //
- .doOnError(t -> onRicCheckedError(t, ricData)) //
- .onErrorResume(throwable -> Mono.empty());
- }
-
- private void onRicCheckedError(Throwable t, RicData ricData) {
- logger.debug("Ric: {} check stopped, exception: {}", ricData.ric.name(), t.getMessage());
- if (t instanceof SynchStartedException) {
- // this is just a temporary state,
- ricData.ric.setState(RicState.AVAILABLE);
- } else {
- ricData.ric.setState(RicState.UNAVAILABLE);
- }
- ricData.ric.getLock().unlockBlocking();
- }
-
- private void onRicCheckedOk(RicData ricData) {
- logger.debug("Ric: {} checked OK", ricData.ric.name());
- ricData.ric.setState(RicState.AVAILABLE);
- ricData.ric.getLock().unlockBlocking();
- }
-
- @SuppressWarnings("squid:S2445") // Blocks should be synchronized on "private final" fields
- private Mono<RicData> setRicState(RicData ric) {
- synchronized (ric) {
- if (ric.ric.getState() == RicState.CONSISTENCY_CHECK) {
- logger.debug("Ric: {} is already being checked", ric.ric.getConfig().name());
- return Mono.empty();
- }
- ric.ric.setState(RicState.CONSISTENCY_CHECK);
- return Mono.just(ric);
- }
- }
-
- private Mono<RicData> createRicData(Ric ric) {
- return Mono.just(ric) //
- .flatMap(aRic -> this.a1ClientFactory.createA1Client(ric)) //
- .flatMap(a1Client -> Mono.just(new RicData(ric, a1Client)));
- }
-
- private Mono<RicData> checkRicState(RicData ric) {
- if (ric.ric.getState() == RicState.UNAVAILABLE) {
- return startSynchronization(ric) //
- .onErrorResume(t -> Mono.empty());
- } else if (ric.ric.getState() == RicState.SYNCHRONIZING || ric.ric.getState() == RicState.CONSISTENCY_CHECK) {
- return Mono.empty();
- } else {
- return Mono.just(ric);
- }
- }
-
- private Mono<RicData> checkRicPolicies(RicData ric) {
- return ric.getClient().getPolicyIdentities() //
- .flatMap(ricP -> validateInstances(ricP, ric));
- }
-
- private Mono<RicData> validateInstances(Collection<String> ricPolicies, RicData ric) {
- synchronized (this.policies) {
- if (ricPolicies.size() != policies.getForRic(ric.ric.name()).size()) {
- return startSynchronization(ric);
- }
-
- for (String policyId : ricPolicies) {
- if (!policies.containsPolicy(policyId)) {
- return startSynchronization(ric);
- }
- }
- return Mono.just(ric);
- }
- }
-
- private Mono<RicData> checkRicPolicyTypes(RicData ric) {
- return ric.getClient().getPolicyTypeIdentities() //
- .flatMap(ricTypes -> validateTypes(ricTypes, ric));
- }
-
- private Mono<RicData> validateTypes(Collection<String> ricTypes, RicData ric) {
- if (ricTypes.size() != ric.ric.getSupportedPolicyTypes().size()) {
- return startSynchronization(ric);
- }
- for (String typeName : ricTypes) {
- if (!ric.ric.isSupportingType(typeName)) {
- return startSynchronization(ric);
- }
- }
- return Mono.just(ric);
- }
-
- private Mono<RicData> startSynchronization(RicData ric) {
- RicSynchronizationTask synchronizationTask = createSynchronizationTask();
- synchronizationTask.run(ric.ric);
- return Mono.error(new SynchStartedException("Syncronization started"));
- }
-
- RicSynchronizationTask createSynchronizationTask() {
- return new RicSynchronizationTask(a1ClientFactory, policyTypes, policies, services);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.tasks;
-
-import static org.oransc.policyagent.repository.Ric.RicState;
-
-import org.oransc.policyagent.clients.A1Client;
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.clients.AsyncRestClient;
-import org.oransc.policyagent.repository.ImmutablePolicyType;
-import org.oransc.policyagent.repository.Lock.LockType;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Service;
-import org.oransc.policyagent.repository.Services;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import reactor.core.publisher.BaseSubscriber;
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-import reactor.core.publisher.SignalType;
-
-/**
- * Synchronizes the content of a RIC with the content in the repository. This
- * means:
- * <p>
- * load all policy types
- * <p>
- * send all policy instances to the RIC
- * <p>
- * if that fails remove all policy instances
- * <p>
- * Notify subscribing services
- */
-@SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally
-public class RicSynchronizationTask {
-
- private static final Logger logger = LoggerFactory.getLogger(RicSynchronizationTask.class);
- static final int CONCURRENCY_RIC = 1; // How may paralell requests that is sent to one NearRT RIC
-
- private final A1ClientFactory a1ClientFactory;
- private final PolicyTypes policyTypes;
- private final Policies policies;
- private final Services services;
-
- public RicSynchronizationTask(A1ClientFactory a1ClientFactory, PolicyTypes policyTypes, Policies policies,
- Services services) {
- this.a1ClientFactory = a1ClientFactory;
- this.policyTypes = policyTypes;
- this.policies = policies;
- this.services = services;
- }
-
- public void run(Ric ric) {
- logger.debug("Handling ric: {}", ric.getConfig().name());
-
- if (ric.getState() == RicState.SYNCHRONIZING) {
- logger.debug("Ric: {} is already being synchronized", ric.getConfig().name());
- return;
- }
-
- ric.getLock().lock(LockType.EXCLUSIVE) //
- .flatMap(notUsed -> setRicState(ric)) //
- .flatMap(lock -> this.a1ClientFactory.createA1Client(ric)) //
- .flatMapMany(client -> runSynchronization(ric, client)) //
- .onErrorResume(throwable -> deleteAllPolicyInstances(ric, throwable))
- .subscribe(new BaseSubscriber<Object>() {
- @Override
- protected void hookOnError(Throwable throwable) {
- logger.warn("Synchronization failure for ric: {}, reason: {}", ric.name(), throwable.getMessage());
- ric.setState(RicState.UNAVAILABLE);
- }
-
- @Override
- protected void hookOnComplete() {
- onSynchronizationComplete(ric);
- }
-
- @Override
- protected void hookFinally(SignalType type) {
- ric.getLock().unlockBlocking();
- }
- });
- }
-
- @SuppressWarnings("squid:S2445") // Blocks should be synchronized on "private final" fields
- private Mono<Ric> setRicState(Ric ric) {
- synchronized (ric) {
- if (ric.getState() == RicState.SYNCHRONIZING) {
- logger.debug("Ric: {} is already being synchronized", ric.getConfig().name());
- return Mono.empty();
- }
- ric.setState(RicState.SYNCHRONIZING);
- return Mono.just(ric);
- }
- }
-
- private Flux<Object> runSynchronization(Ric ric, A1Client a1Client) {
- Flux<PolicyType> synchronizedTypes = synchronizePolicyTypes(ric, a1Client);
- Flux<?> policiesDeletedInRic = a1Client.deleteAllPolicies();
- Flux<Policy> policiesRecreatedInRic = recreateAllPoliciesInRic(ric, a1Client);
-
- return Flux.concat(synchronizedTypes, policiesDeletedInRic, policiesRecreatedInRic);
- }
-
- private void onSynchronizationComplete(Ric ric) {
- logger.debug("Synchronization completed for: {}", ric.name());
- ric.setState(RicState.AVAILABLE);
- notifyAllServices("Synchronization completed for:" + ric.name());
- }
-
- private void notifyAllServices(String body) {
- for (Service service : services.getAll()) {
- String url = service.getCallbackUrl();
- if (url.length() > 0) {
- createNotificationClient(url) //
- .put("", body) //
- .subscribe( //
- notUsed -> logger.debug("Service {} notified", service.getName()),
- throwable -> logger.warn("Service notification failed for service: {}. Cause: {}",
- service.getName(), throwable.getMessage()),
- () -> logger.debug("All services notified"));
- }
- }
- }
-
- private Flux<Object> deleteAllPolicyInstances(Ric ric, Throwable t) {
- logger.debug("Recreation of policies failed for ric: {}, reason: {}", ric.name(), t.getMessage());
- deleteAllPoliciesInRepository(ric);
-
- Flux<PolicyType> synchronizedTypes = this.a1ClientFactory.createA1Client(ric) //
- .flatMapMany(a1Client -> synchronizePolicyTypes(ric, a1Client));
- Flux<?> deletePoliciesInRic = this.a1ClientFactory.createA1Client(ric) //
- .flatMapMany(A1Client::deleteAllPolicies) //
- .doOnComplete(() -> deleteAllPoliciesInRepository(ric));
-
- return Flux.concat(synchronizedTypes, deletePoliciesInRic);
- }
-
- AsyncRestClient createNotificationClient(final String url) {
- return new AsyncRestClient(url, this.a1ClientFactory.getAppConfig().getWebClientConfig());
- }
-
- private Flux<PolicyType> synchronizePolicyTypes(Ric ric, A1Client a1Client) {
- return a1Client.getPolicyTypeIdentities() //
- .doOnNext(x -> ric.clearSupportedPolicyTypes()) //
- .flatMapMany(Flux::fromIterable) //
- .doOnNext(typeId -> logger.debug("For ric: {}, handling type: {}", ric.getConfig().name(), typeId)) //
- .flatMap(policyTypeId -> getPolicyType(policyTypeId, a1Client), CONCURRENCY_RIC) //
- .doOnNext(ric::addSupportedPolicyType); //
- }
-
- private Mono<PolicyType> getPolicyType(String policyTypeId, A1Client a1Client) {
- if (policyTypes.contains(policyTypeId)) {
- return Mono.just(policyTypes.get(policyTypeId));
- }
- return a1Client.getPolicyTypeSchema(policyTypeId) //
- .flatMap(schema -> createPolicyType(policyTypeId, schema));
- }
-
- private Mono<PolicyType> createPolicyType(String policyTypeId, String schema) {
- PolicyType pt = ImmutablePolicyType.builder().name(policyTypeId).schema(schema).build();
- policyTypes.put(pt);
- return Mono.just(pt);
- }
-
- private void deleteAllPoliciesInRepository(Ric ric) {
- for (Policy policy : policies.getForRic(ric.name())) {
- this.policies.remove(policy);
- }
- }
-
- private Flux<Policy> putPolicy(Policy policy, Ric ric, A1Client a1Client) {
- logger.debug("Recreating policy: {}, for ric: {}", policy.id(), ric.getConfig().name());
- return a1Client.putPolicy(policy) //
- .flatMapMany(notUsed -> Flux.just(policy));
- }
-
- private boolean checkTransient(Policy policy) {
- if (policy.isTransient()) {
- this.policies.remove(policy);
- }
- return policy.isTransient();
- }
-
- private Flux<Policy> recreateAllPoliciesInRic(Ric ric, A1Client a1Client) {
- return Flux.fromIterable(policies.getForRic(ric.name())) //
- .filter(policy -> !checkTransient(policy)) //
- .flatMap(policy -> putPolicy(policy, ric, a1Client), CONCURRENCY_RIC);
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.tasks;
-
-import java.time.Duration;
-
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.repository.Lock;
-import org.oransc.policyagent.repository.Lock.LockType;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.Service;
-import org.oransc.policyagent.repository.Services;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.scheduling.annotation.EnableScheduling;
-import org.springframework.stereotype.Component;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-/**
- * Periodically checks that services with a keepAliveInterval set are alive. If
- * a service is deemed not alive, all the service's policies are deleted, both
- * in the repository and in the affected Rics, and the service is removed from
- * the repository. This means that the service needs to register again after
- * this.
- */
-@Component
-@EnableScheduling
-@SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally
-public class ServiceSupervision {
- private static final Logger logger = LoggerFactory.getLogger(ServiceSupervision.class);
- static final int CONCURRENCY_RIC = 1; // How may paralell requests that is sent
- private final Services services;
- private final Policies policies;
- private A1ClientFactory a1ClientFactory;
- private final Duration checkInterval;
-
- @Autowired
- public ServiceSupervision(Services services, Policies policies, A1ClientFactory a1ClientFactory) {
- this(services, policies, a1ClientFactory, Duration.ofMinutes(1));
- }
-
- public ServiceSupervision(Services services, Policies policies, A1ClientFactory a1ClientFactory,
- Duration checkInterval) {
- this.services = services;
- this.policies = policies;
- this.a1ClientFactory = a1ClientFactory;
- this.checkInterval = checkInterval;
- start();
- }
-
- private void start() {
- logger.debug("Checking services starting");
- createTask().subscribe(null, null, () -> logger.error("Checking services unexpectedly terminated"));
- }
-
- private Flux<?> createTask() {
- return Flux.interval(this.checkInterval) //
- .flatMap(notUsed -> checkAllServices());
- }
-
- Flux<Policy> checkAllServices() {
- return Flux.fromIterable(services.getAll()) //
- .filter(Service::isExpired) //
- .doOnNext(service -> logger.info("Service is expired: {}", service.getName())) //
- .doOnNext(service -> services.remove(service.getName())) //
- .flatMap(this::getAllPoliciesForService) //
- .flatMap(this::deletePolicy, CONCURRENCY_RIC);
- }
-
- @SuppressWarnings("squid:S2629") // Invoke method(s) only conditionally
- private Flux<Policy> deletePolicy(Policy policy) {
- Lock lock = policy.ric().getLock();
- return lock.lock(LockType.SHARED) //
- .doOnNext(notUsed -> policies.remove(policy)) //
- .flatMap(notUsed -> deletePolicyInRic(policy))
- .doOnNext(notUsed -> logger.debug("Policy deleted due to service inactivity: {}, service: {}", policy.id(),
- policy.ownerServiceName())) //
- .doOnNext(notUsed -> lock.unlockBlocking()) //
- .doOnError(throwable -> lock.unlockBlocking()) //
- .doOnError(throwable -> logger.debug("Failed to delete inactive policy: {}, reason: {}", policy.id(),
- throwable.getMessage())) //
- .flatMapMany(notUsed -> Flux.just(policy)) //
- .onErrorResume(throwable -> Flux.empty());
- }
-
- private Flux<Policy> getAllPoliciesForService(Service service) {
- return Flux.fromIterable(policies.getForService(service.getName()));
- }
-
- private Mono<Policy> deletePolicyInRic(Policy policy) {
- return a1ClientFactory.createA1Client(policy.ric()) //
- .flatMap(client -> client.deletePolicy(policy) //
- .onErrorResume(exception -> handleDeleteFromRicFailure(policy, exception)) //
- .map(nothing -> policy));
- }
-
- private Mono<String> handleDeleteFromRicFailure(Policy policy, Throwable e) {
- logger.warn("Could not delete policy: {} from ric: {}. Cause: {}", policy.id(), policy.ric().name(),
- e.getMessage());
- return Mono.empty();
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Awaitility.await;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doReturn;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonArray;
-import com.google.gson.JsonElement;
-import com.google.gson.JsonParser;
-
-import java.nio.charset.StandardCharsets;
-import java.time.Duration;
-import java.time.Instant;
-import java.util.ArrayList;
-import java.util.List;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.oransc.policyagent.clients.AsyncRestClient;
-import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.configuration.ImmutableRicConfig;
-import org.oransc.policyagent.configuration.ImmutableWebClientConfig;
-import org.oransc.policyagent.configuration.RicConfig;
-import org.oransc.policyagent.configuration.WebClientConfig;
-import org.oransc.policyagent.controllers.PolicyInfo;
-import org.oransc.policyagent.controllers.ServiceRegistrationInfo;
-import org.oransc.policyagent.controllers.ServiceStatus;
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.oransc.policyagent.repository.ImmutablePolicy;
-import org.oransc.policyagent.repository.ImmutablePolicyType;
-import org.oransc.policyagent.repository.Lock.LockType;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Ric.RicState;
-import org.oransc.policyagent.repository.Rics;
-import org.oransc.policyagent.repository.Services;
-import org.oransc.policyagent.tasks.RicSupervision;
-import org.oransc.policyagent.tasks.ServiceSupervision;
-import org.oransc.policyagent.utils.MockA1Client;
-import org.oransc.policyagent.utils.MockA1ClientFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-import org.springframework.boot.test.context.TestConfiguration;
-import org.springframework.boot.web.embedded.tomcat.TomcatServletWebServerFactory;
-import org.springframework.boot.web.server.LocalServerPort;
-import org.springframework.boot.web.servlet.server.ServletWebServerFactory;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.annotation.Bean;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.test.context.TestPropertySource;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-import reactor.util.annotation.Nullable;
-
-@ExtendWith(SpringExtension.class)
-@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
-@TestPropertySource(
- properties = { //
- "server.ssl.key-store=./config/keystore.jks", //
- "app.webclient.trust-store=./config/truststore.jks"})
-class ApplicationTest {
- private static final Logger logger = LoggerFactory.getLogger(ApplicationTest.class);
-
- @Autowired
- ApplicationContext context;
-
- @Autowired
- private Rics rics;
-
- @Autowired
- private Policies policies;
-
- @Autowired
- private PolicyTypes policyTypes;
-
- @Autowired
- MockA1ClientFactory a1ClientFactory;
-
- @Autowired
- RicSupervision supervision;
-
- @Autowired
- ApplicationConfig applicationConfig;
-
- @Autowired
- Services services;
-
- private static Gson gson = new GsonBuilder() //
- .serializeNulls() //
- .create(); //
-
- public static class MockApplicationConfig extends ApplicationConfig {
- @Override
- public String getLocalConfigurationFilePath() {
- return ""; // No config file loaded for the test
- }
- }
-
- /**
- * Overrides the BeanFactory.
- */
- @TestConfiguration
- static class TestBeanFactory {
- private final PolicyTypes policyTypes = new PolicyTypes();
- private final Services services = new Services();
- private final Policies policies = new Policies();
- MockA1ClientFactory a1ClientFactory = null;
-
- @Bean
- public ApplicationConfig getApplicationConfig() {
- return new MockApplicationConfig();
- }
-
- @Bean
- MockA1ClientFactory getA1ClientFactory() {
- if (a1ClientFactory == null) {
- this.a1ClientFactory = new MockA1ClientFactory(this.policyTypes);
- }
- return this.a1ClientFactory;
- }
-
- @Bean
- public PolicyTypes getPolicyTypes() {
- return this.policyTypes;
- }
-
- @Bean
- Policies getPolicies() {
- return this.policies;
- }
-
- @Bean
- Services getServices() {
- return this.services;
- }
-
- @Bean
- public ServiceSupervision getServiceSupervision() {
- Duration checkInterval = Duration.ofMillis(1);
- return new ServiceSupervision(this.services, this.policies, this.getA1ClientFactory(), checkInterval);
- }
-
- @Bean
- public ServletWebServerFactory servletContainer() {
- return new TomcatServletWebServerFactory();
- }
-
- }
-
- @LocalServerPort
- private int port;
-
- @BeforeEach
- void reset() {
- rics.clear();
- policies.clear();
- policyTypes.clear();
- services.clear();
- a1ClientFactory.reset();
- }
-
- @AfterEach
- void verifyNoRicLocks() {
- for (Ric ric : this.rics.getRics()) {
- ric.getLock().lockBlocking(LockType.EXCLUSIVE);
- ric.getLock().unlockBlocking();
- assertThat(ric.getLock().getLockCounter()).isZero();
- assertThat(ric.getState()).isEqualTo(Ric.RicState.AVAILABLE);
- }
- }
-
- @Test
- void testGetRics() throws Exception {
- addRic("ric1");
- this.addPolicyType("type1", "ric1");
- String url = "/rics?policyType=type1";
- String rsp = restClient().get(url).block();
- assertThat(rsp).contains("ric1");
-
- // nameless type for ORAN A1 1.1
- addRic("ric2");
- this.addPolicyType("", "ric2");
- url = "/rics?policyType=";
-
- // This tests also validation of trusted certs restClient(true)
- rsp = restClient(true).get(url).block();
- assertThat(rsp).contains("ric2") //
- .doesNotContain("ric1") //
- .contains("AVAILABLE");
-
- // All RICs
- rsp = restClient().get("/rics").block();
- assertThat(rsp).contains("ric2") //
- .contains("ric1");
-
- // Non existing policy type
- url = "/rics?policyType=XXXX";
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
- }
-
- @Test
- void testSynchronization() throws Exception {
- // Two polictypes will be put in the NearRT RICs
- PolicyTypes nearRtRicPolicyTypes = new PolicyTypes();
- nearRtRicPolicyTypes.put(createPolicyType("typeName"));
- nearRtRicPolicyTypes.put(createPolicyType("typeName2"));
- this.a1ClientFactory.setPolicyTypes(nearRtRicPolicyTypes);
-
- // One type and one instance added to the agent storage
- final String ric1Name = "ric1";
- Ric ric1 = addRic(ric1Name);
- Policy policy2 = addPolicy("policyId2", "typeName", "service", ric1Name);
- Ric ric2 = addRic("ric2");
-
- getA1Client(ric1Name).putPolicy(policy2); // put it in the RIC
- policies.remove(policy2); // Remove it from the repo -> should be deleted in the RIC
-
- String policyId = "policyId";
- Policy policy = addPolicy(policyId, "typeName", "service", ric1Name); // This should be created in the RIC
- supervision.checkAllRics(); // The created policy should be put in the RIC
-
- // Wait until synch is completed
- await().untilAsserted(() -> RicState.SYNCHRONIZING.equals(rics.getRic(ric1Name).getState()));
- await().untilAsserted(() -> RicState.AVAILABLE.equals(rics.getRic(ric1Name).getState()));
- await().untilAsserted(() -> RicState.AVAILABLE.equals(rics.getRic("ric2").getState()));
-
- Policies ricPolicies = getA1Client(ric1Name).getPolicies();
- assertThat(ricPolicies.size()).isEqualTo(1);
- Policy ricPolicy = ricPolicies.get(policyId);
- assertThat(ricPolicy.json()).isEqualTo(policy.json());
-
- // Both types should be in the agent storage after the synch
- assertThat(ric1.getSupportedPolicyTypes()).hasSize(2);
- assertThat(ric2.getSupportedPolicyTypes()).hasSize(2);
- }
-
- @Test
- void testGetRicForManagedElement_thenReturnCorrectRic() throws Exception {
- String ricName = "ric1";
- String managedElementId = "kista_1";
- addRic(ricName, managedElementId);
-
- String url = "/ric?managedElementId=" + managedElementId;
- String rsp = restClient().get(url).block();
- assertThat(rsp).isEqualTo(ricName);
-
- // test GET RIC for ManagedElement that does not exist
- url = "/ric?managedElementId=" + "junk";
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
- }
-
- private String putPolicyUrl(String serviceName, String ricName, String policyTypeName, String policyInstanceId,
- boolean isTransient) {
- String url;
- if (policyTypeName.isEmpty()) {
- url = "/policy?id=" + policyInstanceId + "&ric=" + ricName + "&service=" + serviceName;
- } else {
- url = "/policy?id=" + policyInstanceId + "&ric=" + ricName + "&service=" + serviceName + "&type="
- + policyTypeName;
- }
- if (isTransient) {
- url += "&transient=true";
- }
- return url;
- }
-
- private String putPolicyUrl(String serviceName, String ricName, String policyTypeName, String policyInstanceId) {
- return putPolicyUrl(serviceName, ricName, policyTypeName, policyInstanceId, false);
- }
-
- @Test
- void testPutPolicy() throws Exception {
- String serviceName = "service1";
- String ricName = "ric1";
- String policyTypeName = "type1";
- String policyInstanceId = "instance1";
-
- putService(serviceName);
- addPolicyType(policyTypeName, ricName);
-
- // PUT a transient policy
- String url = putPolicyUrl(serviceName, ricName, policyTypeName, policyInstanceId, true);
- final String policyBody = jsonString();
- this.rics.getRic(ricName).setState(Ric.RicState.AVAILABLE);
-
- restClient().put(url, policyBody).block();
-
- Policy policy = policies.getPolicy(policyInstanceId);
- assertThat(policy).isNotNull();
- assertThat(policy.id()).isEqualTo(policyInstanceId);
- assertThat(policy.ownerServiceName()).isEqualTo(serviceName);
- assertThat(policy.ric().name()).isEqualTo("ric1");
- assertThat(policy.isTransient()).isTrue();
-
- // Put a non transient policy
- url = putPolicyUrl(serviceName, ricName, policyTypeName, policyInstanceId);
- restClient().put(url, policyBody).block();
- policy = policies.getPolicy(policyInstanceId);
- assertThat(policy.isTransient()).isFalse();
-
- url = "/policies";
- String rsp = restClient().get(url).block();
- assertThat(rsp).as("Response contains policy instance ID.").contains(policyInstanceId);
-
- url = "/policy?id=" + policyInstanceId;
- rsp = restClient().get(url).block();
- assertThat(rsp).isEqualTo(policyBody);
-
- // Test of error codes
- url = putPolicyUrl(serviceName, ricName + "XX", policyTypeName, policyInstanceId);
- testErrorCode(restClient().put(url, policyBody), HttpStatus.NOT_FOUND);
-
- url = putPolicyUrl(serviceName, ricName, policyTypeName + "XX", policyInstanceId);
- addPolicyType(policyTypeName + "XX", "otherRic");
- testErrorCode(restClient().put(url, policyBody), HttpStatus.NOT_FOUND);
-
- url = putPolicyUrl(serviceName, ricName, policyTypeName, policyInstanceId);
- this.rics.getRic(ricName).setState(Ric.RicState.SYNCHRONIZING);
- testErrorCode(restClient().put(url, policyBody), HttpStatus.LOCKED);
- this.rics.getRic(ricName).setState(Ric.RicState.AVAILABLE);
- }
-
- @Test
- /**
- * Test that HttpStatus and body from failing REST call to A1 is passed on to
- * the caller.
- *
- * @throws ServiceException
- */
- void testErrorFromRic() throws ServiceException {
- putService("service1");
- addPolicyType("type1", "ric1");
-
- String url = putPolicyUrl("service1", "ric1", "type1", "id1");
- MockA1Client a1Client = a1ClientFactory.getOrCreateA1Client("ric1");
- HttpStatus httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
- String responseBody = "Refused";
- byte[] responseBodyBytes = responseBody.getBytes(StandardCharsets.UTF_8);
-
- WebClientResponseException a1Exception = new WebClientResponseException(httpStatus.value(), "statusText", null,
- responseBodyBytes, StandardCharsets.UTF_8, null);
- doReturn(Mono.error(a1Exception)).when(a1Client).putPolicy(any());
-
- // PUT Policy
- testErrorCode(restClient().put(url, "{}"), httpStatus, responseBody);
-
- // DELETE POLICY
- this.addPolicy("instance1", "type1", "service1", "ric1");
- doReturn(Mono.error(a1Exception)).when(a1Client).deletePolicy(any());
- testErrorCode(restClient().delete("/policy?id=instance1"), httpStatus, responseBody);
-
- // GET STATUS
- this.addPolicy("instance1", "type1", "service1", "ric1");
- doReturn(Mono.error(a1Exception)).when(a1Client).getPolicyStatus(any());
- testErrorCode(restClient().get("/policy_status?id=instance1"), httpStatus, responseBody);
-
- // Check that empty response body is OK
- a1Exception = new WebClientResponseException(httpStatus.value(), "", null, null, null, null);
- doReturn(Mono.error(a1Exception)).when(a1Client).getPolicyStatus(any());
- testErrorCode(restClient().get("/policy_status?id=instance1"), httpStatus);
- }
-
- @Test
- void testPutTypelessPolicy() throws Exception {
- putService("service1");
- addPolicyType("", "ric1");
- String url = putPolicyUrl("service1", "ric1", "", "id1");
- restClient().put(url, jsonString()).block();
-
- String rsp = restClient().get("/policies").block();
- List<PolicyInfo> info = parseList(rsp, PolicyInfo.class);
- assertThat(info).hasSize(1);
- PolicyInfo policyInfo = info.get(0);
- assertThat(policyInfo.id).isEqualTo("id1");
- assertThat(policyInfo.type).isEmpty();
- }
-
- @Test
- void testRefuseToUpdatePolicy() throws Exception {
- // Test that only the json can be changed for a already created policy
- // In this case service is attempted to be changed
- this.addRic("ric1");
- this.addRic("ricXXX");
- this.addPolicy("instance1", "type1", "service1", "ric1");
- this.addPolicy("instance2", "type1", "service1", "ricXXX");
-
- // Try change ric1 -> ricXXX
- String urlWrongRic = putPolicyUrl("service1", "ricXXX", "type1", "instance1");
- testErrorCode(restClient().put(urlWrongRic, jsonString()), HttpStatus.CONFLICT);
- }
-
- @Test
- void testGetPolicy() throws Exception {
- String url = "/policy?id=id";
- Policy policy = addPolicy("id", "typeName", "service1", "ric1");
- {
- String rsp = restClient().get(url).block();
- assertThat(rsp).isEqualTo(policy.json());
- }
- {
- policies.remove(policy);
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
- }
- }
-
- @Test
- void testDeletePolicy() throws Exception {
- addPolicy("id", "typeName", "service1", "ric1");
- assertThat(policies.size()).isEqualTo(1);
-
- String url = "/policy?id=id";
- ResponseEntity<String> entity = restClient().deleteForEntity(url).block();
-
- assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
- assertThat(policies.size()).isZero();
-
- // Delete a non existing policy
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
- }
-
- @Test
- void testGetPolicySchemas() throws Exception {
- addPolicyType("type1", "ric1");
- addPolicyType("type2", "ric2");
-
- String url = "/policy_schemas";
- String rsp = this.restClient().get(url).block();
- assertThat(rsp).contains("type1") //
- .contains("[{\"title\":\"type2\"}");
-
- List<String> info = parseSchemas(rsp);
- assertThat(info).hasSize(2);
-
- url = "/policy_schemas?ric=ric1";
- rsp = restClient().get(url).block();
- assertThat(rsp).contains("type1");
- info = parseSchemas(rsp);
- assertThat(info).hasSize(1);
-
- // Get schema for non existing RIC
- url = "/policy_schemas?ric=ric1XXX";
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
- }
-
- @Test
- void testGetPolicySchema() throws Exception {
- addPolicyType("type1", "ric1");
- addPolicyType("type2", "ric2");
-
- String url = "/policy_schema?id=type1";
- String rsp = restClient().get(url).block();
- logger.info(rsp);
- assertThat(rsp).contains("type1") //
- .contains("title");
-
- // Get non existing schema
- url = "/policy_schema?id=type1XX";
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
- }
-
- @Test
- void testGetPolicyTypes() throws Exception {
- addPolicyType("type1", "ric1");
- addPolicyType("type2", "ric2");
-
- String url = "/policy_types";
- String rsp = restClient().get(url).block();
- assertThat(rsp).isEqualTo("[\"type2\",\"type1\"]");
-
- url = "/policy_types?ric=ric1";
- rsp = restClient().get(url).block();
- assertThat(rsp).isEqualTo("[\"type1\"]");
-
- // Get policy types for non existing RIC
- url = "/policy_types?ric=ric1XXX";
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
- }
-
- @Test
- void testGetPolicies() throws Exception {
- addPolicy("id1", "type1", "service1");
-
- String url = "/policies";
- String rsp = restClient().get(url).block();
- logger.info(rsp);
- List<PolicyInfo> info = parseList(rsp, PolicyInfo.class);
- assertThat(info).hasSize(1);
- PolicyInfo policyInfo = info.get(0);
- assert (policyInfo.validate());
- assertThat(policyInfo.id).isEqualTo("id1");
- assertThat(policyInfo.type).isEqualTo("type1");
- assertThat(policyInfo.service).isEqualTo("service1");
- }
-
- @Test
- void testGetPoliciesFilter() throws Exception {
- addPolicy("id1", "type1", "service1");
- addPolicy("id2", "type1", "service2");
- addPolicy("id3", "type2", "service1");
-
- String url = "/policies?type=type1";
- String rsp = restClient().get(url).block();
- logger.info(rsp);
- assertThat(rsp).contains("id1") //
- .contains("id2") //
- .doesNotContain("id3");
-
- url = "/policies?type=type1&service=service2";
- rsp = restClient().get(url).block();
- logger.info(rsp);
- assertThat(rsp).doesNotContain("id1") //
- .contains("id2") //
- .doesNotContain("id3");
-
- // Test get policies for non existing type
- url = "/policies?type=type1XXX";
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
-
- // Test get policies for non existing RIC
- url = "/policies?ric=XXX";
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
- }
-
- @Test
- void testGetPolicyIdsFilter() throws Exception {
- addPolicy("id1", "type1", "service1", "ric1");
- addPolicy("id2", "type1", "service2", "ric1");
- addPolicy("id3", "type2", "service1", "ric1");
-
- String url = "/policy_ids?type=type1";
- String rsp = restClient().get(url).block();
- logger.info(rsp);
- assertThat(rsp).contains("id1") //
- .contains("id2") //
- .doesNotContain("id3");
-
- url = "/policy_ids?type=type1&service=service1&ric=ric1";
- rsp = restClient().get(url).block();
- assertThat(rsp).isEqualTo("[\"id1\"]");
-
- // Test get policy ids for non existing type
- url = "/policy_ids?type=type1XXX";
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
-
- // Test get policy ids for non existing RIC
- url = "/policy_ids?ric=XXX";
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
- }
-
- @Test
- void testPutAndGetService() throws Exception {
- // PUT
- String serviceName = "name";
- putService(serviceName, 0, HttpStatus.CREATED);
- putService(serviceName, 0, HttpStatus.OK);
-
- // GET one service
- String url = "/services?name=name";
- String rsp = restClient().get(url).block();
- List<ServiceStatus> info = parseList(rsp, ServiceStatus.class);
- assertThat(info).hasSize(1);
- ServiceStatus status = info.iterator().next();
- assertThat(status.keepAliveIntervalSeconds).isZero();
- assertThat(status.serviceName).isEqualTo(serviceName);
-
- // GET (all)
- url = "/services";
- rsp = restClient().get(url).block();
- assertThat(rsp).as("Response contains service name").contains(serviceName);
- logger.info(rsp);
-
- // Keep alive
- url = "/services/keepalive?name=name";
- ResponseEntity<String> entity = restClient().putForEntity(url).block();
- assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
-
- // DELETE service
- assertThat(services.size()).isEqualTo(1);
- url = "/services?name=name";
- restClient().delete(url).block();
- assertThat(services.size()).isZero();
-
- // Keep alive, no registered service
- testErrorCode(restClient().put("/services/keepalive?name=name", ""), HttpStatus.NOT_FOUND);
-
- // PUT servive with bad payload
- testErrorCode(restClient().put("/service", "crap"), HttpStatus.BAD_REQUEST);
- testErrorCode(restClient().put("/service", "{}"), HttpStatus.BAD_REQUEST);
- testErrorCode(restClient().put("/service", createServiceJson(serviceName, -123)), HttpStatus.BAD_REQUEST);
- testErrorCode(restClient().put("/service", createServiceJson(serviceName, 0, "missing.portandprotocol.com")),
- HttpStatus.BAD_REQUEST);
-
- // GET non existing service
- testErrorCode(restClient().get("/services?name=XXX"), HttpStatus.NOT_FOUND);
- }
-
- @Test
- void testServiceSupervision() throws Exception {
- putService("service1", 1, HttpStatus.CREATED);
- addPolicyType("type1", "ric1");
-
- String url = putPolicyUrl("service1", "ric1", "type1", "instance1");
- final String policyBody = jsonString();
- restClient().put(url, policyBody).block();
-
- assertThat(policies.size()).isEqualTo(1);
- assertThat(services.size()).isEqualTo(1);
-
- // Timeout after ~1 second
- await().untilAsserted(() -> assertThat(policies.size()).isZero());
- assertThat(services.size()).isZero();
- }
-
- @Test
- void testGetPolicyStatus() throws Exception {
- addPolicy("id", "typeName", "service1", "ric1");
- assertThat(policies.size()).isEqualTo(1);
-
- String url = "/policy_status?id=id";
- String rsp = restClient().get(url).block();
- assertThat(rsp).isEqualTo("OK");
-
- // GET non existing policy status
- url = "/policy_status?id=XXX";
- testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
- }
-
- private Policy addPolicy(String id, String typeName, String service, String ric) throws ServiceException {
- addRic(ric);
- Policy policy = ImmutablePolicy.builder() //
- .id(id) //
- .json(jsonString()) //
- .ownerServiceName(service) //
- .ric(rics.getRic(ric)) //
- .type(addPolicyType(typeName, ric)) //
- .lastModified("lastModified") //
- .isTransient(false) //
- .build();
- policies.put(policy);
- return policy;
- }
-
- private Policy addPolicy(String id, String typeName, String service) throws ServiceException {
- return addPolicy(id, typeName, service, "ric");
- }
-
- private String createServiceJson(String name, long keepAliveIntervalSeconds) {
- return createServiceJson(name, keepAliveIntervalSeconds, "https://examples.javacodegeeks.com/core-java/");
- }
-
- private String createServiceJson(String name, long keepAliveIntervalSeconds, String url) {
- ServiceRegistrationInfo service = new ServiceRegistrationInfo(name, keepAliveIntervalSeconds, url);
-
- String json = gson.toJson(service);
- return json;
- }
-
- private void putService(String name) {
- putService(name, 0, null);
- }
-
- private void putService(String name, long keepAliveIntervalSeconds, @Nullable HttpStatus expectedStatus) {
- String url = "/service";
- String body = createServiceJson(name, keepAliveIntervalSeconds);
- ResponseEntity<String> resp = restClient().putForEntity(url, body).block();
- if (expectedStatus != null) {
- assertEquals(expectedStatus, resp.getStatusCode(), "");
- }
- }
-
- private String baseUrl() {
- return "https://localhost:" + port;
- }
-
- private String jsonString() {
- return "{\"servingCellNrcgi\":\"1\"}";
- }
-
- @Test
- void testConcurrency() throws Exception {
- final Instant startTime = Instant.now();
- List<Thread> threads = new ArrayList<>();
- a1ClientFactory.setResponseDelay(Duration.ofMillis(1));
- addRic("ric");
- addPolicyType("type1", "ric");
- addPolicyType("type2", "ric");
- List<ConcurrencyTestRunnable> tests = new ArrayList<>();
-
- for (int i = 0; i < 10; ++i) {
- ConcurrencyTestRunnable test =
- new ConcurrencyTestRunnable(restClient(), supervision, a1ClientFactory, rics, policyTypes);
- Thread thread = new Thread(test, "TestThread_" + i);
- thread.start();
- threads.add(thread);
- tests.add(test);
- }
- for (Thread t : threads) {
- t.join();
- }
- for (ConcurrencyTestRunnable test : tests) {
- assertThat(test.isFailed()).isFalse();
- }
-
- assertThat(policies.size()).isZero();
- logger.info("Concurrency test took " + Duration.between(startTime, Instant.now()));
- }
-
- private AsyncRestClient restClient(boolean useTrustValidation) {
- WebClientConfig config = this.applicationConfig.getWebClientConfig();
- config = ImmutableWebClientConfig.builder() //
- .keyStoreType(config.keyStoreType()) //
- .keyStorePassword(config.keyStorePassword()) //
- .keyStore(config.keyStore()) //
- .keyPassword(config.keyPassword()) //
- .isTrustStoreUsed(useTrustValidation) //
- .trustStore(config.trustStore()) //
- .trustStorePassword(config.trustStorePassword()) //
- .build();
-
- return new AsyncRestClient(baseUrl(), config);
- }
-
- private AsyncRestClient restClient() {
- return restClient(false);
- }
-
- private void testErrorCode(Mono<?> request, HttpStatus expStatus) {
- testErrorCode(request, expStatus, "");
- }
-
- private void testErrorCode(Mono<?> request, HttpStatus expStatus, String responseContains) {
- StepVerifier.create(request) //
- .expectSubscription() //
- .expectErrorMatches(t -> checkWebClientError(t, expStatus, responseContains)) //
- .verify();
- }
-
- private boolean checkWebClientError(Throwable throwable, HttpStatus expStatus, String responseContains) {
- assertTrue(throwable instanceof WebClientResponseException);
- WebClientResponseException responseException = (WebClientResponseException) throwable;
- assertThat(responseException.getStatusCode()).isEqualTo(expStatus);
- assertThat(responseException.getResponseBodyAsString()).contains(responseContains);
- return true;
- }
-
- private MockA1Client getA1Client(String ricName) throws ServiceException {
- return a1ClientFactory.getOrCreateA1Client(ricName);
- }
-
- private PolicyType createPolicyType(String policyTypeName) {
- return ImmutablePolicyType.builder() //
- .name(policyTypeName) //
- .schema("{\"title\":\"" + policyTypeName + "\"}") //
- .build();
- }
-
- private PolicyType addPolicyType(String policyTypeName, String ricName) {
- PolicyType type = createPolicyType(policyTypeName);
- policyTypes.put(type);
- addRic(ricName).addSupportedPolicyType(type);
- return type;
- }
-
- private Ric addRic(String ricName) {
- return addRic(ricName, null);
- }
-
- private Ric addRic(String ricName, String managedElement) {
- if (rics.get(ricName) != null) {
- return rics.get(ricName);
- }
- List<String> mes = new ArrayList<>();
- if (managedElement != null) {
- mes.add(managedElement);
- }
- RicConfig conf = ImmutableRicConfig.builder() //
- .name(ricName) //
- .baseUrl(ricName) //
- .managedElementIds(mes) //
- .controllerName("") //
- .build();
- Ric ric = new Ric(conf);
- ric.setState(Ric.RicState.AVAILABLE);
- this.rics.put(ric);
- return ric;
- }
-
- private static <T> List<T> parseList(String jsonString, Class<T> clazz) {
- List<T> result = new ArrayList<>();
- JsonArray jsonArr = JsonParser.parseString(jsonString).getAsJsonArray();
- for (JsonElement jsonElement : jsonArr) {
- T json = gson.fromJson(jsonElement.toString(), clazz);
- result.add(json);
- }
- return result;
- }
-
- private static List<String> parseSchemas(String jsonString) {
- JsonArray arrayOfSchema = JsonParser.parseString(jsonString).getAsJsonArray();
- List<String> result = new ArrayList<>();
- for (JsonElement schemaObject : arrayOfSchema) {
- result.add(schemaObject.toString());
- }
- return result;
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.oransc.policyagent.clients.AsyncRestClient;
-import org.oransc.policyagent.repository.ImmutablePolicy;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Rics;
-import org.oransc.policyagent.tasks.RicSupervision;
-import org.oransc.policyagent.utils.MockA1Client;
-import org.oransc.policyagent.utils.MockA1ClientFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.ResponseEntity;
-
-/**
- * Invoke operations over the NBI and start synchronizations in a separate
- * thread. For test of robustness using concurrent clients.
- */
-class ConcurrencyTestRunnable implements Runnable {
- private static final Logger logger = LoggerFactory.getLogger(ConcurrencyTestRunnable.class);
- private final AsyncRestClient webClient;
- static AtomicInteger nextCount = new AtomicInteger(0);
- private final int count;
- private final RicSupervision supervision;
- private final MockA1ClientFactory a1ClientFactory;
- private final Rics rics;
- private final PolicyTypes types;
- private boolean failed = false;
-
- ConcurrencyTestRunnable(AsyncRestClient webClient, RicSupervision supervision, MockA1ClientFactory a1ClientFactory,
- Rics rics, PolicyTypes types) {
- this.count = nextCount.incrementAndGet();
- this.supervision = supervision;
- this.a1ClientFactory = a1ClientFactory;
- this.rics = rics;
- this.types = types;
- this.webClient = webClient;
- }
-
- private void printStatusInfo() {
- try {
- String url = "/actuator/metrics/jvm.threads.live";
- ResponseEntity<String> result = webClient.getForEntity(url).block();
- System.out.println(Thread.currentThread() + result.getBody());
-
- url = "/rics";
- result = webClient.getForEntity(url).block();
- System.out.println(Thread.currentThread() + result.getBody());
-
- } catch (Exception e) {
- logger.error(Thread.currentThread() + "Concurrency test printStatusInfo exception " + e.toString());
- }
- }
-
- @Override
- public void run() {
- try {
- for (int i = 0; i < 500; ++i) {
- if (i % 100 == 0) {
- createInconsistency();
- this.supervision.checkAllRics();
- }
- String name = "policy:" + count + ":" + i;
- putPolicy(name);
- putPolicy(name + "-");
- listPolicies();
- listTypes();
- deletePolicy(name);
- deletePolicy(name + "-");
- }
- } catch (Exception e) {
- logger.error("Concurrency test exception " + e.toString());
- printStatusInfo();
- failed = true;
- }
- }
-
- public boolean isFailed() {
- return this.failed;
- }
-
- private Policy createPolicyObject(String id) {
- Ric ric = this.rics.get("ric");
- PolicyType type = this.types.get("type1");
- return ImmutablePolicy.builder() //
- .id(id) //
- .json("{}") //
- .type(type) //
- .ric(ric) //
- .ownerServiceName("") //
- .lastModified("") //
- .isTransient(false) //
- .build();
- }
-
- private void createInconsistency() {
- MockA1Client client = a1ClientFactory.getOrCreateA1Client("ric");
- Policy policy = createPolicyObject("junk");
- client.putPolicy(policy).block();
-
- }
-
- private void listPolicies() {
- String uri = "/policies";
- webClient.getForEntity(uri).block();
- }
-
- private void listTypes() {
- String uri = "/policy_types";
- webClient.getForEntity(uri).block();
- }
-
- private void putPolicy(String name) {
- String putUrl = "/policy?type=type1&id=" + name + "&ric=ric&service=service1";
- webClient.putForEntity(putUrl, "{}").block();
- }
-
- private void deletePolicy(String name) {
- String deleteUrl = "/policy?id=" + name;
- webClient.delete(deleteUrl).block();
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent;
-
-import static org.awaitility.Awaitility.await;
-
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.nio.file.Files;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.repository.ImmutablePolicy;
-import org.oransc.policyagent.repository.ImmutablePolicyType;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Rics;
-import org.oransc.policyagent.utils.MockA1ClientFactory;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.context.SpringBootTest.WebEnvironment;
-import org.springframework.boot.test.context.TestConfiguration;
-import org.springframework.boot.web.server.LocalServerPort;
-import org.springframework.context.annotation.Bean;
-import org.springframework.test.context.TestPropertySource;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.util.StringUtils;
-
-@ExtendWith(SpringExtension.class)
-@SpringBootTest(webEnvironment = WebEnvironment.DEFINED_PORT)
-@TestPropertySource(
- properties = { //
- "server.ssl.key-store=./config/keystore.jks", //
- "app.webclient.trust-store=./config/truststore.jks"})
-class MockPolicyAgent {
- private static final Logger logger = LoggerFactory.getLogger(MockPolicyAgent.class);
-
- @Autowired
- Rics rics;
-
- @Autowired
- Policies policies;
-
- @Autowired
- PolicyTypes policyTypes;
-
- @Autowired
- ApplicationConfig applicationConfig;
-
- static class MockApplicationConfig extends ApplicationConfig {
- @Override
- public String getLocalConfigurationFilePath() {
- URL url = MockApplicationConfig.class.getClassLoader().getResource("test_application_configuration.json");
- return url.getFile();
- }
- }
-
- /**
- * Overrides the BeanFactory.
- */
- @TestConfiguration
- static class TestBeanFactory {
-
- private final Rics rics = new Rics();
- private final Policies policies = new Policies();
- private final PolicyTypes policyTypes = new PolicyTypes();
-
- @Bean
- public ApplicationConfig getApplicationConfig() {
- return new MockApplicationConfig();
- }
-
- @Bean
- public MockA1ClientFactory getA1ClientFactory() {
- PolicyTypes ricTypes = new PolicyTypes();
- loadTypes(ricTypes);
- return new MockA1ClientFactory(ricTypes);
- }
-
- @Bean
- public Policies getPolicies() {
- return this.policies;
- }
-
- @Bean
- public PolicyTypes getPolicyTypes() {
- return this.policyTypes;
- }
-
- @Bean
- public Rics getRics() {
- return this.rics;
- }
-
- private static File[] getResourceFolderFiles(String folder) {
- return getFile(folder).listFiles();
- }
-
- private static String readFile(File file) throws IOException {
- return new String(Files.readAllBytes(file.toPath()));
- }
-
- private void loadTypes(PolicyTypes policyTypes) {
- File[] files = getResourceFolderFiles("policy_types/");
- for (File file : files) {
- try {
- String schema = readFile(file);
- String typeName = title(schema);
- PolicyType type = ImmutablePolicyType.builder().name(typeName).schema(schema).build();
- policyTypes.put(type);
- } catch (Exception e) {
- logger.error("Could not load json schema ", e);
- }
- }
- policyTypes.put(ImmutablePolicyType.builder().name("").schema("{}").build());
- }
- }
-
- private static File getFile(String path) {
- ClassLoader loader = Thread.currentThread().getContextClassLoader();
- URL url = loader.getResource(path);
- return new File(url.getPath());
- }
-
- @LocalServerPort
- private int port;
-
- private void keepServerAlive() throws InterruptedException, IOException {
- waitForConfigurationToBeLoaded();
- loadInstances();
- logger.info("Keeping server alive!");
- synchronized (this) {
- this.wait();
- }
- }
-
- private void waitForConfigurationToBeLoaded() throws IOException {
- String json = getConfigJsonFromFile();
- try {
- int noOfRicsInConfigFile = StringUtils.countOccurrencesOf(json, "baseUrl");
- await().until(() -> rics.size() == noOfRicsInConfigFile);
- } catch (Exception e) {
- logger.info("Loaded rics: {}, and no of rics in config file: {} never matched!", rics.size(),
- StringUtils.countOccurrencesOf(json, "baseUrl"));
- }
- }
-
- private static String title(String jsonSchema) {
- JsonObject parsedSchema = (JsonObject) JsonParser.parseString(jsonSchema);
- String title = parsedSchema.get("title").getAsString();
- return title;
- }
-
- private void loadInstances() throws IOException {
- PolicyType unnamedPolicyType = policyTypes.get("");
- Ric ric = rics.get("ric1");
- String json = getConfigJsonFromFile();
-
- Policy policy = ImmutablePolicy.builder() //
- .id("typelessPolicy") //
- .json(json) //
- .ownerServiceName("MockPolicyAgent") //
- .ric(ric) //
- .type(unnamedPolicyType) //
- .lastModified("now") //
- .isTransient(false) //
- .build();
- this.policies.put(policy);
- }
-
- private String getConfigJsonFromFile() throws IOException {
- File jsonFile = getFile("test_application_configuration.json");
- String json = new String(Files.readAllBytes(jsonFile.toPath()));
- return json;
- }
-
- @Test
- @SuppressWarnings("squid:S2699") // Tests should include assertions. This test is only for keeping the server
- // alive, so it will only be confusing to add an assertion.
- void runMock() throws Exception {
- keepServerAlive();
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.aspect;
-
-import static ch.qos.logback.classic.Level.TRACE;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.never;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.read.ListAppender;
-
-import org.aspectj.lang.ProceedingJoinPoint;
-import org.aspectj.lang.reflect.MethodSignature;
-import org.junit.Rule;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.MockitoJUnit;
-import org.mockito.junit.MockitoRule;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.oransc.policyagent.utils.LoggingUtils;
-
-@ExtendWith(MockitoExtension.class)
-class LogAspectTest {
- @Rule
- MockitoRule mockitoRule = MockitoJUnit.rule();
-
- @Mock
- private ProceedingJoinPoint proceedingJoinPoint;
-
- @Mock
- private MethodSignature methodSignature;
-
- private LogAspect sampleAspect = new LogAspect();
-
- @Test
- void testExecutetimeTime_shouldLogTime() throws Throwable {
- when(proceedingJoinPoint.getSignature()).thenReturn(methodSignature);
- when(methodSignature.getDeclaringType()).thenReturn(this.getClass());
-
- final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(LogAspect.class, TRACE);
-
- sampleAspect.executimeTime(proceedingJoinPoint);
- // 'proceed()' is called exactly once
- verify(proceedingJoinPoint, times(1)).proceed();
- // 'proceed(Object[])' is never called
- verify(proceedingJoinPoint, never()).proceed(null);
-
- assertThat(logAppender.list.get(0).getFormattedMessage()).startsWith("Execution time of");
- }
-
- @Test
- void testEntryLog_shouldLogEntry() throws Throwable {
- when(proceedingJoinPoint.getSignature()).thenReturn(methodSignature);
- String signature = "signature";
- when(methodSignature.getName()).thenReturn(signature);
-
- final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(LogAspect.class, TRACE);
-
- sampleAspect.entryLog(proceedingJoinPoint);
-
- assertThat(logAppender.list.get(0).getFormattedMessage()).isEqualTo("Entering method: " + signature);
- }
-
- @Test
- void testExitLog_shouldLogExit() throws Throwable {
- when(proceedingJoinPoint.getSignature()).thenReturn(methodSignature);
- String signature = "signature";
- when(methodSignature.getName()).thenReturn(signature);
-
- final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(LogAspect.class, TRACE);
-
- sampleAspect.exitLog(proceedingJoinPoint);
-
- assertThat(logAppender.list.get(0).getFormattedMessage()).isEqualTo("Exiting method: " + signature);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
-import java.util.Vector;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.oransc.policyagent.clients.A1Client.A1ProtocolType;
-import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.configuration.ControllerConfig;
-import org.oransc.policyagent.configuration.ImmutableControllerConfig;
-import org.oransc.policyagent.configuration.ImmutableRicConfig;
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.oransc.policyagent.repository.Ric;
-
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-
-@ExtendWith(MockitoExtension.class)
-class A1ClientFactoryTest {
- private static final String RIC_NAME = "Name";
- private static final String EXCEPTION_MESSAGE = "Error";
-
- @Mock
- private ApplicationConfig applicationConfigMock;
-
- @Mock
- A1Client clientMock1;
-
- @Mock
- A1Client clientMock2;
-
- @Mock
- A1Client clientMock3;
-
- @Mock
- A1Client clientMock4;
-
- private Ric ric;
- private A1ClientFactory factoryUnderTest;
-
- private static ImmutableRicConfig ricConfig(String controllerName) {
- return ImmutableRicConfig.builder() //
- .name(RIC_NAME) //
- .baseUrl("baseUrl") //
- .managedElementIds(new Vector<>()) //
- .controllerName(controllerName) //
- .build();
- }
-
- @BeforeEach
- void createFactoryUnderTest() {
- factoryUnderTest = spy(new A1ClientFactory(applicationConfigMock));
- this.ric = new Ric(ricConfig(""));
-
- }
-
- @Test
- void getProtocolVersion_ok() throws ServiceException {
- whenGetProtocolVersionThrowException(clientMock1);
- whenGetProtocolVersionReturn(clientMock2, A1ProtocolType.STD_V1_1);
- doReturn(clientMock1, clientMock2).when(factoryUnderTest).createClient(any(), any());
-
- A1Client client = factoryUnderTest.createA1Client(ric).block();
-
- assertEquals(clientMock2, client, "Not correct client returned");
- assertEquals(A1ProtocolType.STD_V1_1, ric.getProtocolVersion(), "Not correct protocol");
- }
-
- @Test
- void getProtocolVersion_ok_Last() throws ServiceException {
- whenGetProtocolVersionThrowException(clientMock1, clientMock2, clientMock3);
- whenGetProtocolVersionReturn(clientMock4, A1ProtocolType.STD_V1_1);
- doReturn(clientMock1, clientMock2, clientMock3, clientMock4).when(factoryUnderTest).createClient(any(), any());
-
- A1Client client = factoryUnderTest.createA1Client(ric).block();
-
- assertEquals(clientMock4, client, "Not correct client returned");
- assertEquals(A1ProtocolType.STD_V1_1, ric.getProtocolVersion(), "Not correct protocol");
- }
-
- @Test
- void getProtocolVersion_error() throws ServiceException {
- whenGetProtocolVersionThrowException(clientMock1, clientMock2, clientMock3, clientMock4);
- doReturn(clientMock1, clientMock2, clientMock3, clientMock4).when(factoryUnderTest).createClient(any(), any());
-
- StepVerifier.create(factoryUnderTest.createA1Client(ric)) //
- .expectSubscription() //
- .expectError() //
- .verify();
-
- assertEquals(A1ProtocolType.UNKNOWN, ric.getProtocolVersion(), "Protocol negotiation failed for " + ric.name());
- }
-
- private A1Client createClient(A1ProtocolType version) throws ServiceException {
- return factoryUnderTest.createClient(ric, version);
- }
-
- @Test
- void create_check_types() throws ServiceException {
- assertTrue(createClient(A1ProtocolType.STD_V1_1) instanceof StdA1ClientVersion1);
- assertTrue(createClient(A1ProtocolType.OSC_V1) instanceof OscA1Client);
- }
-
- @Test
- void create_check_types_controllers() throws ServiceException {
- this.ric = new Ric(ricConfig("anythingButEmpty"));
- whenGetGetControllerConfigReturn();
- assertTrue(createClient(A1ProtocolType.SDNC_ONAP) instanceof SdncOnapA1Client);
-
- whenGetGetControllerConfigReturn();
- assertTrue(createClient(A1ProtocolType.SDNC_OSC_STD_V1_1) instanceof SdncOscA1Client);
-
- whenGetGetControllerConfigReturn();
- assertTrue(createClient(A1ProtocolType.SDNC_OSC_OSC_V1) instanceof SdncOscA1Client);
- }
-
- private void whenGetProtocolVersionThrowException(A1Client... clientMocks) {
- for (A1Client clientMock : clientMocks) {
- when(clientMock.getProtocolVersion()).thenReturn(Mono.error(new Exception(EXCEPTION_MESSAGE)));
- }
- }
-
- private void whenGetProtocolVersionReturn(A1Client clientMock, A1ProtocolType protocol) {
- when(clientMock.getProtocolVersion()).thenReturn(Mono.just(protocol));
- }
-
- private void whenGetGetControllerConfigReturn() throws ServiceException {
- ControllerConfig controllerCfg = ImmutableControllerConfig.builder() //
- .name("name") //
- .baseUrl("baseUrl") //
- .password("pass") //
- .userName("user") //
- .build();
- when(applicationConfigMock.getControllerConfig(any())).thenReturn(controllerCfg);
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import java.util.Arrays;
-import java.util.Vector;
-
-import org.json.JSONObject;
-import org.oransc.policyagent.configuration.ImmutableRicConfig;
-import org.oransc.policyagent.configuration.RicConfig;
-import org.oransc.policyagent.repository.ImmutablePolicy;
-import org.oransc.policyagent.repository.ImmutablePolicyType;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.repository.Ric;
-import reactor.core.publisher.Mono;
-
-public class A1ClientHelper {
-
- private A1ClientHelper() {
- }
-
- protected static Mono<String> createOutputJsonResponse(String key, String value) {
- JSONObject paramsJson = new JSONObject();
- paramsJson.put(key, value);
- JSONObject responseJson = new JSONObject();
- responseJson.put("output", paramsJson);
- return Mono.just(responseJson.toString());
- }
-
- protected static Ric createRic(String url) {
- RicConfig cfg = ImmutableRicConfig.builder().name("ric") //
- .baseUrl(url) //
- .managedElementIds(new Vector<String>(Arrays.asList("kista_1", "kista_2"))) //
- .controllerName("") //
- .build();
- return new Ric(cfg);
- }
-
- protected static Policy createPolicy(String nearRtRicUrl, String policyId, String json, String type) {
- return ImmutablePolicy.builder() //
- .id(policyId) //
- .json(json) //
- .ownerServiceName("service") //
- .ric(createRic(nearRtRicUrl)) //
- .type(createPolicyType(type)) //
- .lastModified("now") //
- .isTransient(false) //
- .build();
- }
-
- protected static PolicyType createPolicyType(String name) {
- return ImmutablePolicyType.builder().name(name).schema("schema").build();
- }
-
- protected static String getCreateSchema(String policyType, String policyTypeId) {
- JSONObject obj = new JSONObject(policyType);
- JSONObject schemaObj = obj.getJSONObject("create_schema");
- schemaObj.put("title", policyTypeId);
- return schemaObj.toString();
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import io.netty.util.internal.logging.InternalLoggerFactory;
-import io.netty.util.internal.logging.JdkLoggerFactory;
-
-import java.io.IOException;
-
-import okhttp3.mockwebserver.MockResponse;
-import okhttp3.mockwebserver.MockWebServer;
-
-import org.junit.jupiter.api.AfterAll;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.MediaType;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-import reactor.util.Loggers;
-
-class AsyncRestClientTest {
- private static final String BASE_URL = "BaseUrl";
- private static final String REQUEST_URL = "/test";
- private static final String USERNAME = "username";
- private static final String PASSWORD = "password";
- private static final String TEST_JSON = "{\"type\":\"type1\"}";
- private static final int SUCCESS_CODE = 200;
- private static final int ERROR_CODE = 500;
-
- private static MockWebServer mockWebServer;
-
- private static AsyncRestClient clientUnderTest;
-
- @BeforeAll
- static void init() {
- // skip a lot of unnecessary logs from MockWebServer
- InternalLoggerFactory.setDefaultFactory(JdkLoggerFactory.INSTANCE);
- Loggers.useJdkLoggers();
- mockWebServer = new MockWebServer();
- clientUnderTest = new AsyncRestClient(mockWebServer.url(BASE_URL).toString());
- }
-
- @AfterAll
- static void tearDown() throws IOException {
- mockWebServer.shutdown();
- }
-
- @Test
- void testGetNoError() {
- mockWebServer.enqueue(new MockResponse().setResponseCode(SUCCESS_CODE) //
- .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) //
- .setBody(TEST_JSON));
-
- Mono<String> returnedMono = clientUnderTest.get(REQUEST_URL);
- StepVerifier.create(returnedMono).expectNext(TEST_JSON).expectComplete().verify();
- }
-
- @Test
- void testGetError() {
- mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
-
- Mono<String> returnedMono = clientUnderTest.get(REQUEST_URL);
- StepVerifier.create(returnedMono)
- .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
- }
-
- @Test
- void testPutNoError() {
- mockWebServer.enqueue(new MockResponse().setResponseCode(SUCCESS_CODE) //
- .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) //
- .setBody(TEST_JSON));
-
- Mono<String> returnedMono = clientUnderTest.put(REQUEST_URL, TEST_JSON);
- StepVerifier.create(returnedMono).expectNext(TEST_JSON).expectComplete().verify();
- }
-
- @Test
- void testPutError() {
- mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
-
- Mono<String> returnedMono = clientUnderTest.put(REQUEST_URL, TEST_JSON);
- StepVerifier.create(returnedMono)
- .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
- }
-
- @Test
- void testDeleteNoError() {
- mockWebServer.enqueue(new MockResponse().setResponseCode(SUCCESS_CODE));
-
- Mono<String> returnedMono = clientUnderTest.delete(REQUEST_URL);
- StepVerifier.create(returnedMono).expectNext("").expectComplete().verify();
- }
-
- @Test
- void testDeleteError() {
- mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
-
- Mono<String> returnedMono = clientUnderTest.delete(REQUEST_URL);
- StepVerifier.create(returnedMono)
- .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
- }
-
- @Test
- void testPostNoError() {
- mockWebServer.enqueue(new MockResponse().setResponseCode(SUCCESS_CODE) //
- .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) //
- .setBody(TEST_JSON));
-
- Mono<String> returnedMono = clientUnderTest.post(REQUEST_URL, TEST_JSON);
- StepVerifier.create(returnedMono).expectNext(TEST_JSON).expectComplete().verify();
- }
-
- @Test
- void testPostError() {
- mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
-
- Mono<String> returnedMono = clientUnderTest.post(REQUEST_URL, TEST_JSON);
- StepVerifier.create(returnedMono)
- .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
- }
-
- @Test
- void testPostWithAuthHeaderNoError() {
- mockWebServer.enqueue(new MockResponse().setResponseCode(SUCCESS_CODE) //
- .setHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE) //
- .setBody(TEST_JSON));
-
- Mono<String> returnedMono = clientUnderTest.postWithAuthHeader(REQUEST_URL, TEST_JSON, USERNAME, PASSWORD);
- StepVerifier.create(returnedMono).expectNext(TEST_JSON).expectComplete().verify();
- }
-
- @Test
- void testPostWithAuthHeaderError() {
- mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
-
- Mono<String> returnedMono = clientUnderTest.postWithAuthHeader(REQUEST_URL, TEST_JSON, USERNAME, PASSWORD);
- StepVerifier.create(returnedMono)
- .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.json.JSONException;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.oransc.policyagent.configuration.ImmutableRicConfig;
-import org.oransc.policyagent.configuration.RicConfig;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-
-@ExtendWith(MockitoExtension.class)
-class OscA1ClientTest {
-
- private static final String RIC_URL = "RicUrl";
-
- private static final String RIC_BASE_URL = "RicBaseUrl/a1-p";
-
- private static final String POLICYTYPES_IDENTITIES_URL = RIC_BASE_URL + "/policytypes";
- private static final String POLICIES = "/policies";
- private static final String POLICYTYPES_URL = RIC_BASE_URL + "/policytypes/";
- private static final String POLICY_TYPE_1_ID = "type1";
- private static final String POLICY_TYPE_2_ID = "type2";
- private static final String POLICY_TYPE_SCHEMA_VALID = "{\"type\":\"type1\"}";
- private static final String POLICY_TYPE_SCHEMA_INVALID = "\"type\":\"type1\"}";
- private static final String POLICY_1_ID = "policy1";
- private static final String POLICY_2_ID = "policy2";
- private static final String POLICY_JSON_VALID = "{\"policyId\":\"policy1\"}";
-
- OscA1Client clientUnderTest;
-
- AsyncRestClient asyncRestClientMock;
-
- @BeforeEach
- void init() {
- RicConfig ricConfig = ImmutableRicConfig.builder() //
- .name("name") //
- .baseUrl("RicBaseUrl") //
- .managedElementIds(new ArrayList<>()) //
- .controllerName("") //
- .build();
- asyncRestClientMock = mock(AsyncRestClient.class);
- clientUnderTest = new OscA1Client(ricConfig, asyncRestClientMock);
- }
-
- @Test
- void testGetPolicyTypeIdentities() {
- List<String> policyTypeIds = Arrays.asList(POLICY_TYPE_1_ID, POLICY_TYPE_2_ID);
- Mono<String> policyTypeIdsResp = Mono.just(policyTypeIds.toString());
- when(asyncRestClientMock.get(anyString())).thenReturn(policyTypeIdsResp);
-
- Mono<List<String>> returnedMono = clientUnderTest.getPolicyTypeIdentities();
- verify(asyncRestClientMock).get(POLICYTYPES_IDENTITIES_URL);
- StepVerifier.create(returnedMono).expectNext(policyTypeIds).expectComplete().verify();
- }
-
- @Test
- void testGetPolicyIdentities() {
- Mono<String> policyTypeIdsResp = Mono.just(Arrays.asList(POLICY_TYPE_1_ID, POLICY_TYPE_2_ID).toString());
- Mono<String> policyIdsType1Resp = Mono.just(Arrays.asList(POLICY_1_ID).toString());
- Mono<String> policyIdsType2Resp = Mono.just(Arrays.asList(POLICY_2_ID).toString());
- when(asyncRestClientMock.get(anyString())).thenReturn(policyTypeIdsResp).thenReturn(policyIdsType1Resp)
- .thenReturn(policyIdsType2Resp);
-
- List<String> returned = clientUnderTest.getPolicyIdentities().block();
-
- assertEquals(2, returned.size(), "");
- verify(asyncRestClientMock).get(POLICYTYPES_IDENTITIES_URL);
- verify(asyncRestClientMock).get(POLICYTYPES_URL + POLICY_TYPE_1_ID + POLICIES);
- verify(asyncRestClientMock).get(POLICYTYPES_URL + POLICY_TYPE_2_ID + POLICIES);
- }
-
- @Test
- void testGetValidPolicyType() {
- String policyType = "{\"create_schema\": " + POLICY_TYPE_SCHEMA_VALID + "}";
- Mono<String> policyTypeResp = Mono.just(policyType);
-
- when(asyncRestClientMock.get(anyString())).thenReturn(policyTypeResp);
-
- Mono<String> returnedMono = clientUnderTest.getPolicyTypeSchema(POLICY_TYPE_1_ID);
- verify(asyncRestClientMock).get(POLICYTYPES_URL + POLICY_TYPE_1_ID);
- StepVerifier.create(returnedMono).expectNext(A1ClientHelper.getCreateSchema(policyType, POLICY_TYPE_1_ID))
- .expectComplete().verify();
- }
-
- @Test
- void testGetInValidPolicyTypeJson() {
- String policyType = "{\"create_schema\": " + POLICY_TYPE_SCHEMA_INVALID + "}";
- Mono<String> policyTypeResp = Mono.just(policyType);
-
- when(asyncRestClientMock.get(anyString())).thenReturn(policyTypeResp);
-
- Mono<String> returnedMono = clientUnderTest.getPolicyTypeSchema(POLICY_TYPE_1_ID);
- verify(asyncRestClientMock).get(POLICYTYPES_URL + POLICY_TYPE_1_ID);
- StepVerifier.create(returnedMono).expectErrorMatches(throwable -> throwable instanceof JSONException).verify();
- }
-
- @Test
- void testGetPolicyTypeWithoutCreateSchema() {
- Mono<String> policyTypeResp = Mono.just(POLICY_TYPE_SCHEMA_VALID);
-
- when(asyncRestClientMock.get(anyString())).thenReturn(policyTypeResp);
-
- Mono<String> returnedMono = clientUnderTest.getPolicyTypeSchema(POLICY_TYPE_1_ID);
- verify(asyncRestClientMock).get(POLICYTYPES_URL + POLICY_TYPE_1_ID);
- StepVerifier.create(returnedMono).expectErrorMatches(throwable -> throwable instanceof Exception).verify();
- }
-
- @Test
- void testPutPolicy() {
- when(asyncRestClientMock.put(anyString(), anyString())).thenReturn(Mono.empty());
-
- clientUnderTest
- .putPolicy(A1ClientHelper.createPolicy(RIC_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE_1_ID)).block();
- verify(asyncRestClientMock).put(POLICYTYPES_URL + POLICY_TYPE_1_ID + POLICIES + "/" + POLICY_1_ID,
- POLICY_JSON_VALID);
- }
-
- @Test
- void testDeletePolicy() {
- when(asyncRestClientMock.delete(anyString())).thenReturn(Mono.empty());
-
- Mono<String> returnedMono = clientUnderTest
- .deletePolicy(A1ClientHelper.createPolicy(RIC_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE_1_ID));
- verify(asyncRestClientMock).delete(POLICYTYPES_URL + POLICY_TYPE_1_ID + POLICIES + "/" + POLICY_1_ID);
- StepVerifier.create(returnedMono).expectComplete().verify();
- }
-
- @Test
- void testDeleteAllPolicies() {
- Mono<String> policyTypeIdsResp = Mono.just(Arrays.asList(POLICY_TYPE_1_ID, POLICY_TYPE_2_ID).toString());
- Mono<String> policyIdsType1Resp = Mono.just(Arrays.asList(POLICY_1_ID).toString());
- Mono<String> policyIdsType2Resp = Mono.just(Arrays.asList(POLICY_2_ID).toString());
- when(asyncRestClientMock.get(anyString())).thenReturn(policyTypeIdsResp).thenReturn(policyIdsType1Resp)
- .thenReturn(policyIdsType2Resp);
- when(asyncRestClientMock.delete(anyString())).thenReturn(Mono.empty());
-
- Flux<String> returnedFlux = clientUnderTest.deleteAllPolicies();
- StepVerifier.create(returnedFlux).expectComplete().verify();
- verify(asyncRestClientMock).get(POLICYTYPES_IDENTITIES_URL);
- verify(asyncRestClientMock).get(POLICYTYPES_URL + POLICY_TYPE_1_ID + POLICIES);
- verify(asyncRestClientMock).delete(POLICYTYPES_URL + POLICY_TYPE_1_ID + POLICIES + "/" + POLICY_1_ID);
- verify(asyncRestClientMock).get(POLICYTYPES_URL + POLICY_TYPE_2_ID + POLICIES);
- verify(asyncRestClientMock).delete(POLICYTYPES_URL + POLICY_TYPE_2_ID + POLICIES + "/" + POLICY_2_ID);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-import org.json.JSONException;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.mockito.stubbing.OngoingStubbing;
-import org.oransc.policyagent.configuration.ControllerConfig;
-import org.oransc.policyagent.configuration.ImmutableControllerConfig;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-
-@ExtendWith(MockitoExtension.class)
-class SdncOnapA1ClientTest {
- private static final String CONTROLLER_USERNAME = "username";
- private static final String CONTROLLER_PASSWORD = "password";
- private static final String RIC_1_URL = "RicUrl";
- private static final String POLICYTYPES_IDENTITIES_URL = "/A1-ADAPTER-API:getPolicyTypes";
- private static final String POLICIES_IDENTITIES_URL = "/A1-ADAPTER-API:getPolicyInstances";
- private static final String POLICYTYPES_URL = "/A1-ADAPTER-API:getPolicyType";
- private static final String PUT_POLICY_URL = "/A1-ADAPTER-API:createPolicyInstance";
- private static final String DELETE_POLICY_URL = "/A1-ADAPTER-API:deletePolicyInstance";
-
- private static final String POLICY_TYPE_1_ID = "type1";
- private static final String POLICY_TYPE_2_ID = "type2";
- private static final String POLICY_TYPE_SCHEMA_VALID = "{\"type\":\"type1\"}";
- private static final String POLICY_TYPE_SCHEMA_INVALID = "\"type\":\"type1\"}";
- private static final String POLICY_1_ID = "policy1";
- private static final String POLICY_2_ID = "policy2";
- private static final String POLICY_JSON_VALID = "{\"scope\":{\"ueId\":\"ue1\"}}";
-
- SdncOnapA1Client clientUnderTest;
-
- AsyncRestClient asyncRestClientMock;
-
- @BeforeEach
- void init() {
- asyncRestClientMock = mock(AsyncRestClient.class);
- ControllerConfig controllerCfg = ImmutableControllerConfig.builder() //
- .name("name") //
- .baseUrl("baseUrl") //
- .password(CONTROLLER_PASSWORD) //
- .userName(CONTROLLER_USERNAME) //
- .build();
-
- clientUnderTest =
- new SdncOnapA1Client(A1ClientHelper.createRic(RIC_1_URL).getConfig(), controllerCfg, asyncRestClientMock);
- }
-
- @Test
- void testGetPolicyTypeIdentities() {
- SdncOnapA1Client.SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .build();
- String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
-
- List<String> policyTypeIds = Arrays.asList(POLICY_TYPE_1_ID, POLICY_TYPE_2_ID);
- Mono<String> policyTypeIdsResp =
- A1ClientHelper.createOutputJsonResponse("policy-type-id-list", policyTypeIds.toString());
- whenAsyncPostThenReturn(policyTypeIdsResp);
-
- Mono<List<String>> returnedMono = clientUnderTest.getPolicyTypeIdentities();
- verify(asyncRestClientMock).postWithAuthHeader(POLICYTYPES_IDENTITIES_URL, inputJsonString, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
- StepVerifier.create(returnedMono).expectNext(policyTypeIds).expectComplete().verify();
- }
-
- @Test
- void testGetPolicyIdentities() {
- SdncOnapA1Client.SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .build();
- String inputJsonStringGetTypeIds = SdncJsonHelper.createInputJsonString(inputParams);
- inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .policyTypeId(POLICY_TYPE_1_ID) //
- .build();
- String inputJsonStringGetPolicyIdsType1 = SdncJsonHelper.createInputJsonString(inputParams);
- inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .policyTypeId(POLICY_TYPE_2_ID) //
- .build();
- String inputJsonStringGetPolicyIdsType2 = SdncJsonHelper.createInputJsonString(inputParams);
-
- List<String> policyTypeIds = Arrays.asList(POLICY_TYPE_1_ID, POLICY_TYPE_2_ID);
- Mono<String> policyTypeIdsResp =
- A1ClientHelper.createOutputJsonResponse("policy-type-id-list", policyTypeIds.toString());
- List<String> policyIdsType1 = Arrays.asList(POLICY_1_ID);
- Mono<String> policyIdsType1Resp =
- A1ClientHelper.createOutputJsonResponse("policy-instance-id-list", policyIdsType1.toString());
- List<String> policyIdsType2 = Arrays.asList(POLICY_2_ID);
- Mono<String> policyIdsType2Resp =
- A1ClientHelper.createOutputJsonResponse("policy-instance-id-list", policyIdsType2.toString());
- whenAsyncPostThenReturn(policyTypeIdsResp).thenReturn(policyIdsType1Resp).thenReturn(policyIdsType2Resp);
-
- Mono<List<String>> returnedMono = clientUnderTest.getPolicyIdentities();
- StepVerifier.create(returnedMono).expectNext(Arrays.asList(POLICY_1_ID, POLICY_2_ID)).expectComplete().verify();
- verify(asyncRestClientMock).postWithAuthHeader(POLICYTYPES_IDENTITIES_URL, inputJsonStringGetTypeIds,
- CONTROLLER_USERNAME, CONTROLLER_PASSWORD);
- verify(asyncRestClientMock).postWithAuthHeader(POLICIES_IDENTITIES_URL, inputJsonStringGetPolicyIdsType1,
- CONTROLLER_USERNAME, CONTROLLER_PASSWORD);
- verify(asyncRestClientMock).postWithAuthHeader(POLICIES_IDENTITIES_URL, inputJsonStringGetPolicyIdsType2,
- CONTROLLER_USERNAME, CONTROLLER_PASSWORD);
- }
-
- @Test
- void testGetValidPolicyType() {
- SdncOnapA1Client.SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .policyTypeId(POLICY_TYPE_1_ID) //
- .build();
- String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
-
- String policyType = "{\"policySchema\": " + POLICY_TYPE_SCHEMA_VALID + ", \"statusSchema\": {} }";
- Mono<String> policyTypeResp = A1ClientHelper.createOutputJsonResponse("policy-type", policyType);
- whenAsyncPostThenReturn(policyTypeResp);
-
- Mono<String> returnedMono = clientUnderTest.getPolicyTypeSchema(POLICY_TYPE_1_ID);
- verify(asyncRestClientMock).postWithAuthHeader(POLICYTYPES_URL, inputJsonString, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
- StepVerifier.create(returnedMono).expectNext(POLICY_TYPE_SCHEMA_VALID).expectComplete().verify();
- }
-
- @Test
- void testGetInvalidPolicyType() {
- SdncOnapA1Client.SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .policyTypeId(POLICY_TYPE_1_ID) //
- .build();
- String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
-
- String policyType = "{\"policySchema\": " + POLICY_TYPE_SCHEMA_INVALID + ", \"statusSchema\": {} }";
- Mono<String> policyTypeResp = A1ClientHelper.createOutputJsonResponse("policy-type", policyType);
- whenAsyncPostThenReturn(policyTypeResp);
-
- Mono<String> returnedMono = clientUnderTest.getPolicyTypeSchema(POLICY_TYPE_1_ID);
- verify(asyncRestClientMock).postWithAuthHeader(POLICYTYPES_URL, inputJsonString, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
- StepVerifier.create(returnedMono).expectErrorMatches(throwable -> throwable instanceof JSONException).verify();
- }
-
- @Test
- void testPutPolicy() {
- SdncOnapA1Client.SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .policyTypeId(POLICY_TYPE_1_ID) //
- .policyInstanceId(POLICY_1_ID) //
- .policyInstance(POLICY_JSON_VALID) //
- .properties(new ArrayList<String>()) //
- .build();
- String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
-
- whenAsyncPostThenReturn(Mono.empty());
-
- Mono<String> returnedMono = clientUnderTest
- .putPolicy(A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE_1_ID));
- verify(asyncRestClientMock).postWithAuthHeader(PUT_POLICY_URL, inputJsonString, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
- StepVerifier.create(returnedMono).expectComplete().verify();
- }
-
- @Test
- void testDeletePolicy() {
- SdncOnapA1Client.SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .policyTypeId(POLICY_TYPE_1_ID) //
- .policyInstanceId(POLICY_1_ID) //
- .build();
- String inputJsonString = SdncJsonHelper.createInputJsonString(inputParams);
-
- whenAsyncPostThenReturn(Mono.empty());
-
- Mono<String> returnedMono = clientUnderTest
- .deletePolicy(A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE_1_ID));
- verify(asyncRestClientMock).postWithAuthHeader(DELETE_POLICY_URL, inputJsonString, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
- StepVerifier.create(returnedMono).expectComplete().verify();
- }
-
- @Test
- void testDeleteAllPolicies() {
- SdncOnapA1Client.SdncOnapAdapterInput inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .build();
- String inputJsonStringGetTypeIds = SdncJsonHelper.createInputJsonString(inputParams);
- inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .policyTypeId(POLICY_TYPE_1_ID) //
- .build();
- String inputJsonStringGetPolicyIdsType1 = SdncJsonHelper.createInputJsonString(inputParams);
- inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .policyTypeId(POLICY_TYPE_2_ID) //
- .build();
- String inputJsonStringGetPolicyIdsType2 = SdncJsonHelper.createInputJsonString(inputParams);
- inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .policyTypeId(POLICY_TYPE_1_ID) //
- .policyInstanceId(POLICY_1_ID) //
- .build();
- String inputJsonStringDeletePolicy1 = SdncJsonHelper.createInputJsonString(inputParams);
- inputParams = ImmutableSdncOnapAdapterInput.builder() //
- .nearRtRicId(RIC_1_URL) //
- .policyTypeId(POLICY_TYPE_2_ID) //
- .policyInstanceId(POLICY_2_ID) //
- .build();
- String inputJsonStringDeletePolicy2 = SdncJsonHelper.createInputJsonString(inputParams);
-
- List<String> policyTypeIds = Arrays.asList(POLICY_TYPE_1_ID, POLICY_TYPE_2_ID);
- Mono<String> policyTypeIdsResp =
- A1ClientHelper.createOutputJsonResponse("policy-type-id-list", policyTypeIds.toString());
- List<String> policyIdsType1 = Arrays.asList(POLICY_1_ID);
- Mono<String> policyIdsType1Resp =
- A1ClientHelper.createOutputJsonResponse("policy-instance-id-list", policyIdsType1.toString());
- List<String> policyIdsType2 = Arrays.asList(POLICY_2_ID);
- Mono<String> policyIdsType2Resp =
- A1ClientHelper.createOutputJsonResponse("policy-instance-id-list", policyIdsType2.toString());
- whenAsyncPostThenReturn(policyTypeIdsResp).thenReturn(policyIdsType1Resp).thenReturn(Mono.empty())
- .thenReturn(policyIdsType2Resp).thenReturn(Mono.empty());
-
- Flux<String> returnedFlux = clientUnderTest.deleteAllPolicies();
- StepVerifier.create(returnedFlux).expectComplete().verify();
- verify(asyncRestClientMock).postWithAuthHeader(POLICYTYPES_IDENTITIES_URL, inputJsonStringGetTypeIds,
- CONTROLLER_USERNAME, CONTROLLER_PASSWORD);
- verify(asyncRestClientMock).postWithAuthHeader(POLICIES_IDENTITIES_URL, inputJsonStringGetPolicyIdsType1,
- CONTROLLER_USERNAME, CONTROLLER_PASSWORD);
- verify(asyncRestClientMock).postWithAuthHeader(DELETE_POLICY_URL, inputJsonStringDeletePolicy1,
- CONTROLLER_USERNAME, CONTROLLER_PASSWORD);
- verify(asyncRestClientMock).postWithAuthHeader(POLICIES_IDENTITIES_URL, inputJsonStringGetPolicyIdsType2,
- CONTROLLER_USERNAME, CONTROLLER_PASSWORD);
- verify(asyncRestClientMock).postWithAuthHeader(DELETE_POLICY_URL, inputJsonStringDeletePolicy2,
- CONTROLLER_USERNAME, CONTROLLER_PASSWORD);
- }
-
- private OngoingStubbing<Mono<String>> whenAsyncPostThenReturn(Mono<String> response) {
- return when(asyncRestClientMock.postWithAuthHeader(anyString(), anyString(), anyString(), anyString()))
- .thenReturn(response);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import static org.junit.Assert.fail;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import com.google.gson.Gson;
-import com.google.gson.JsonElement;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.nio.file.Files;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Optional;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.mockito.stubbing.OngoingStubbing;
-import org.oransc.policyagent.clients.A1Client.A1ProtocolType;
-import org.oransc.policyagent.clients.ImmutableAdapterOutput.Builder;
-import org.oransc.policyagent.clients.SdncOscA1Client.AdapterOutput;
-import org.oransc.policyagent.clients.SdncOscA1Client.AdapterRequest;
-import org.oransc.policyagent.configuration.ControllerConfig;
-import org.oransc.policyagent.configuration.ImmutableControllerConfig;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.Ric;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-
-@ExtendWith(MockitoExtension.class)
-class SdncOscA1ClientTest {
- private static final String CONTROLLER_USERNAME = "username";
- private static final String CONTROLLER_PASSWORD = "password";
- private static final String RIC_1_URL = "RicUrl";
- private static final String GET_A1_POLICY_URL = "/A1-ADAPTER-API:getA1Policy";
- private static final String PUT_A1_URL = "/A1-ADAPTER-API:putA1Policy";
- private static final String DELETE_A1_URL = "/A1-ADAPTER-API:deleteA1Policy";
- private static final String GET_A1_POLICY_STATUS_URL = "/A1-ADAPTER-API:getA1PolicyStatus";
- private static final String POLICY_TYPE_1_ID = "type1";
- private static final String POLICY_1_ID = "policy1";
- private static final String POLICY_2_ID = "policy2";
- private static final String POLICY_JSON_VALID = "{\"scope\":{\"ueId\":\"ue1\"}}";
-
- SdncOscA1Client clientUnderTest;
-
- @Mock
- AsyncRestClient asyncRestClientMock;
-
- private ControllerConfig controllerConfig() {
- return ImmutableControllerConfig.builder() //
- .name("name") //
- .baseUrl("baseUrl") //
- .password(CONTROLLER_PASSWORD) //
- .userName(CONTROLLER_USERNAME) //
- .build();
- }
-
- @BeforeEach
- void init() {
- Ric ric = A1ClientHelper.createRic(RIC_1_URL);
-
- clientUnderTest = new SdncOscA1Client(A1ProtocolType.SDNC_OSC_STD_V1_1, ric.getConfig(), controllerConfig(),
- asyncRestClientMock);
- }
-
- @Test
- void createClientWithWrongProtocol_thenErrorIsThrown() {
- try {
- new SdncOscA1Client(A1ProtocolType.STD_V1_1, null, null, new AsyncRestClient("", null));
- fail("Should have thrown exception.");
- } catch (IllegalArgumentException e) {
- return;
- }
- }
-
- @Test
- void getPolicyTypeIdentities_STD() {
- List<String> policyTypeIds = clientUnderTest.getPolicyTypeIdentities().block();
- assertEquals(1, policyTypeIds.size(), "should hardcoded to one");
- assertEquals("", policyTypeIds.get(0), "should hardcoded to empty");
- }
-
- @Test
- void getPolicyTypeIdentities_OSC() {
- clientUnderTest = new SdncOscA1Client(A1ProtocolType.SDNC_OSC_OSC_V1, //
- A1ClientHelper.createRic(RIC_1_URL).getConfig(), //
- controllerConfig(), asyncRestClientMock);
-
- String response = createOkResponseWithBody(Arrays.asList(POLICY_TYPE_1_ID));
- whenAsyncPostThenReturn(Mono.just(response));
-
- List<String> policyTypeIds = clientUnderTest.getPolicyTypeIdentities().block();
-
- assertEquals(1, policyTypeIds.size());
- assertEquals(POLICY_TYPE_1_ID, policyTypeIds.get(0));
-
- String expUrl = RIC_1_URL + "/a1-p/policytypes";
- ImmutableAdapterRequest expectedParams = ImmutableAdapterRequest.builder() //
- .nearRtRicUrl(expUrl) //
- .build();
- String expInput = SdncJsonHelper.createInputJsonString(expectedParams);
- verify(asyncRestClientMock).postWithAuthHeader(GET_A1_POLICY_URL, expInput, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
- }
-
- @Test
- void getTypeSchema_STD() {
- String policyType = clientUnderTest.getPolicyTypeSchema("").block();
-
- assertEquals("{}", policyType);
- }
-
- @Test
- void getTypeSchema_OSC() throws IOException {
- clientUnderTest = new SdncOscA1Client(A1ProtocolType.SDNC_OSC_OSC_V1, //
- A1ClientHelper.createRic(RIC_1_URL).getConfig(), //
- controllerConfig(), asyncRestClientMock);
-
- String ricResponse = loadFile("test_osc_get_schema_response.json");
- JsonElement elem = gson().fromJson(ricResponse, JsonElement.class);
- String responseFromController = createOkResponseWithBody(elem);
- whenAsyncPostThenReturn(Mono.just(responseFromController));
-
- String response = clientUnderTest.getPolicyTypeSchema("policyTypeId").block();
-
- JsonElement respJson = gson().fromJson(response, JsonElement.class);
- assertEquals("policyTypeId", respJson.getAsJsonObject().get("title").getAsString(),
- "title should be updated to contain policyType ID");
- }
-
- @Test
- void parseJsonArrayOfString() {
- // One integer and one string
- String inputString = "[1, \"1\" ]";
-
- List<String> result = SdncJsonHelper.parseJsonArrayOfString(inputString).collectList().block();
- assertEquals(2, result.size());
- assertEquals("1", result.get(0));
- assertEquals("1", result.get(1));
- }
-
- @Test
- void getPolicyIdentities_STD() {
-
- String policyIdsResp = createOkResponseWithBody(Arrays.asList(POLICY_1_ID, POLICY_2_ID));
- whenAsyncPostThenReturn(Mono.just(policyIdsResp));
-
- List<String> returned = clientUnderTest.getPolicyIdentities().block();
-
- assertEquals(2, returned.size());
-
- ImmutableAdapterRequest expectedParams = ImmutableAdapterRequest.builder() //
- .nearRtRicUrl(policiesUrl()) //
- .build();
- String expInput = SdncJsonHelper.createInputJsonString(expectedParams);
- verify(asyncRestClientMock).postWithAuthHeader(GET_A1_POLICY_URL, expInput, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
-
- }
-
- @Test
- void getPolicyIdentities_OSC() {
- clientUnderTest = new SdncOscA1Client(A1ProtocolType.SDNC_OSC_OSC_V1, //
- A1ClientHelper.createRic(RIC_1_URL).getConfig(), //
- controllerConfig(), asyncRestClientMock);
-
- String policytypeIdsResp = createOkResponseWithBody(Arrays.asList(POLICY_TYPE_1_ID));
- String policyIdsResp = createOkResponseWithBody(Arrays.asList(POLICY_1_ID, POLICY_2_ID));
- whenAsyncPostThenReturn(Mono.just(policytypeIdsResp)).thenReturn(Mono.just(policyIdsResp));
-
- List<String> returned = clientUnderTest.getPolicyIdentities().block();
-
- assertEquals(2, returned.size());
-
- ImmutableAdapterRequest expectedParams = ImmutableAdapterRequest.builder() //
- .nearRtRicUrl(RIC_1_URL + "/a1-p/policytypes/type1/policies") //
- .build();
- String expInput = SdncJsonHelper.createInputJsonString(expectedParams);
- verify(asyncRestClientMock).postWithAuthHeader(GET_A1_POLICY_URL, expInput, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
- }
-
- @Test
- void putPolicyValidResponse() {
- whenPostReturnOkResponse();
-
- String returned = clientUnderTest
- .putPolicy(A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE_1_ID))
- .block();
-
- assertEquals("OK", returned);
- final String expUrl = policiesUrl() + "/" + POLICY_1_ID;
- AdapterRequest expectedInputParams = ImmutableAdapterRequest.builder() //
- .nearRtRicUrl(expUrl) //
- .body(POLICY_JSON_VALID) //
- .build();
- String expInput = SdncJsonHelper.createInputJsonString(expectedInputParams);
-
- verify(asyncRestClientMock).postWithAuthHeader(PUT_A1_URL, expInput, CONTROLLER_USERNAME, CONTROLLER_PASSWORD);
- }
-
- @Test
- void putPolicyRejected() {
- final String policyJson = "{}";
- AdapterOutput adapterOutput = ImmutableAdapterOutput.builder() //
- .body("NOK") //
- .httpStatus(HttpStatus.BAD_REQUEST.value()) // ERROR
- .build();
-
- String resp = SdncJsonHelper.createOutputJsonString(adapterOutput);
- whenAsyncPostThenReturn(Mono.just(resp));
-
- Mono<String> returnedMono = clientUnderTest
- .putPolicy(A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, policyJson, POLICY_TYPE_1_ID));
- StepVerifier.create(returnedMono) //
- .expectSubscription() //
- .expectErrorMatches(t -> t instanceof WebClientResponseException) //
- .verify();
-
- final String expUrl = policiesUrl() + "/" + POLICY_1_ID;
- AdapterRequest expRequestParams = ImmutableAdapterRequest.builder() //
- .nearRtRicUrl(expUrl) //
- .body(policyJson) //
- .build();
- String expRequest = SdncJsonHelper.createInputJsonString(expRequestParams);
- verify(asyncRestClientMock).postWithAuthHeader(PUT_A1_URL, expRequest, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
- StepVerifier.create(returnedMono)
- .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
- }
-
- @Test
- void deletePolicy() {
- whenPostReturnOkResponse();
-
- String returned = clientUnderTest
- .deletePolicy(A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE_1_ID))
- .block();
-
- assertEquals("OK", returned);
- final String expUrl = policiesUrl() + "/" + POLICY_1_ID;
- AdapterRequest expectedInputParams = ImmutableAdapterRequest.builder() //
- .nearRtRicUrl(expUrl) //
- .build();
- String expInput = SdncJsonHelper.createInputJsonString(expectedInputParams);
-
- verify(asyncRestClientMock).postWithAuthHeader(DELETE_A1_URL, expInput, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
- }
-
- @Test
- void getStatus() {
- whenPostReturnOkResponse();
-
- Policy policy = A1ClientHelper.createPolicy(RIC_1_URL, POLICY_1_ID, POLICY_JSON_VALID, POLICY_TYPE_1_ID);
-
- String returnedStatus = clientUnderTest.getPolicyStatus(policy).block();
-
- assertEquals("OK", returnedStatus, "unexpected status");
-
- final String expUrl = policiesUrl() + "/" + POLICY_1_ID + "/status";
- AdapterRequest expectedInputParams = ImmutableAdapterRequest.builder() //
- .nearRtRicUrl(expUrl) //
- .build();
- String expInput = SdncJsonHelper.createInputJsonString(expectedInputParams);
-
- verify(asyncRestClientMock).postWithAuthHeader(GET_A1_POLICY_STATUS_URL, expInput, CONTROLLER_USERNAME,
- CONTROLLER_PASSWORD);
- }
-
- @Test
- void getVersion_STD() {
- whenPostReturnOkResponse();
-
- A1ProtocolType returnedVersion = clientUnderTest.getProtocolVersion().block();
-
- assertEquals(A1ProtocolType.SDNC_OSC_STD_V1_1, returnedVersion);
-
- whenPostReturnOkResponseNoBody();
-
- returnedVersion = clientUnderTest.getProtocolVersion().block();
-
- assertEquals(A1ProtocolType.SDNC_OSC_STD_V1_1, returnedVersion);
- }
-
- @Test
- void getVersion_OSC() {
- clientUnderTest = new SdncOscA1Client(A1ProtocolType.SDNC_OSC_OSC_V1, //
- A1ClientHelper.createRic(RIC_1_URL).getConfig(), //
- controllerConfig(), asyncRestClientMock);
-
- whenAsyncPostThenReturn(Mono.error(new Exception("Error"))).thenReturn(Mono.just(createOkResponseString(true)));
-
- A1ProtocolType returnedVersion = clientUnderTest.getProtocolVersion().block();
-
- assertEquals(A1ProtocolType.SDNC_OSC_OSC_V1, returnedVersion);
- }
-
- private String policiesUrl() {
- return RIC_1_URL + "/A1-P/v1/policies";
- }
-
- private Gson gson() {
- return SdncOscA1Client.gson;
- }
-
- private String loadFile(String fileName) throws IOException {
- ClassLoader loader = Thread.currentThread().getContextClassLoader();
- URL url = loader.getResource(fileName);
- File file = new File(url.getFile());
- return new String(Files.readAllBytes(file.toPath()));
- }
-
- private void whenPostReturnOkResponse() {
- whenAsyncPostThenReturn(Mono.just(createOkResponseString(true)));
- }
-
- private void whenPostReturnOkResponseNoBody() {
- whenAsyncPostThenReturn(Mono.just(createOkResponseString(false)));
- }
-
- private String createOkResponseWithBody(Object body) {
- AdapterOutput output = ImmutableAdapterOutput.builder() //
- .body(gson().toJson(body)) //
- .httpStatus(HttpStatus.OK.value()) //
- .build();
- return SdncJsonHelper.createOutputJsonString(output);
- }
-
- private String createOkResponseString(boolean withBody) {
- Builder responseBuilder = ImmutableAdapterOutput.builder().httpStatus(HttpStatus.OK.value());
- if (withBody) {
- responseBuilder.body(HttpStatus.OK.name());
- } else {
- responseBuilder.body(Optional.empty());
- }
- return SdncJsonHelper.createOutputJsonString(responseBuilder.build());
- }
-
- private OngoingStubbing<Mono<String>> whenAsyncPostThenReturn(Mono<String> response) {
- return when(asyncRestClientMock.postWithAuthHeader(anyString(), anyString(), anyString(), anyString()))
- .thenReturn(response);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.clients;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import java.util.Arrays;
-import java.util.List;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.oransc.policyagent.configuration.RicConfig;
-import org.oransc.policyagent.repository.Policy;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-
-@ExtendWith(MockitoExtension.class)
-class StdA1ClientTest {
- private static final String RIC_URL = "RicUrl";
- private static final String POLICY_TYPE_1_NAME = "type1";
- private static final String POLICY_1_ID = "policy1";
- private static final String POLICY_2_ID = "policy2";
- private static final String POLICY_JSON = "{\"policyId\":\"policy1\"}";
- private static final String POLICY_TYPE = "typeName";
-
- StdA1ClientVersion1 clientUnderTest;
-
- @Mock
- AsyncRestClient asyncRestClientMock;
-
- @Mock
- RicConfig ricConfigMock;
-
- @BeforeEach
- void init() {
- clientUnderTest = new StdA1ClientVersion1(asyncRestClientMock, ricConfigMock);
- }
-
- private String policiesUrl() {
- return RIC_URL + "/A1-P/v1/policies";
- }
-
- private String policiesBaseUrl() {
- return policiesUrl() + "/";
- }
-
- @Test
- void testGetPolicyTypeIdentities() {
- List<String> policyTypeIds = clientUnderTest.getPolicyTypeIdentities().block();
- assertEquals(1, policyTypeIds.size(), "should hardcoded to one");
- assertEquals("", policyTypeIds.get(0), "should hardcoded to empty");
- }
-
- @Test
- void testGetPolicyIdentities() {
- doReturn(RIC_URL).when(ricConfigMock).baseUrl();
- Mono<String> policyIds = Mono.just(Arrays.asList(POLICY_1_ID, POLICY_2_ID).toString());
- when(asyncRestClientMock.get(anyString())).thenReturn(policyIds);
-
- List<String> result = clientUnderTest.getPolicyIdentities().block();
- assertEquals(2, result.size(), "");
-
- verify(asyncRestClientMock).get(policiesUrl());
- }
-
- @Test
- void testGetValidPolicyType() {
- String policyType = clientUnderTest.getPolicyTypeSchema(POLICY_TYPE_1_NAME).block();
- assertEquals("{}", policyType, "");
- }
-
- @Test
- void testPutPolicyValidResponse() {
- doReturn(RIC_URL).when(ricConfigMock).baseUrl();
- when(asyncRestClientMock.put(anyString(), anyString())).thenReturn(Mono.just(POLICY_JSON));
-
- Mono<String> policyMono =
- clientUnderTest.putPolicy(A1ClientHelper.createPolicy(RIC_URL, POLICY_1_ID, POLICY_JSON, POLICY_TYPE));
-
- verify(asyncRestClientMock).put(policiesBaseUrl() + POLICY_1_ID, POLICY_JSON);
- StepVerifier.create(policyMono).expectNext(POLICY_JSON).expectComplete().verify();
- }
-
- @Test
- void testDeletePolicy() {
- doReturn(RIC_URL).when(ricConfigMock).baseUrl();
- final String url = policiesBaseUrl() + POLICY_1_ID;
- when(asyncRestClientMock.delete(url)).thenReturn(Mono.empty());
-
- Policy policy = A1ClientHelper.createPolicy(RIC_URL, POLICY_1_ID, POLICY_JSON, POLICY_TYPE);
- Mono<?> responseMono = clientUnderTest.deletePolicy(policy);
- verify(asyncRestClientMock).delete(url);
- StepVerifier.create(responseMono).expectComplete().verify();
- }
-
- @Test
- void testDeleteAllPolicies() {
- doReturn(RIC_URL).when(ricConfigMock).baseUrl();
- Mono<String> policyIds = Mono.just(Arrays.asList(POLICY_1_ID, POLICY_2_ID).toString());
- when(asyncRestClientMock.get(policiesUrl())).thenReturn(policyIds);
- when(asyncRestClientMock.delete(anyString())).thenReturn(Mono.empty());
-
- Flux<String> responseFlux = clientUnderTest.deleteAllPolicies();
- StepVerifier.create(responseFlux).expectComplete().verify();
- verify(asyncRestClientMock).get(policiesUrl());
- verify(asyncRestClientMock).delete(policiesBaseUrl() + POLICY_1_ID);
- verify(asyncRestClientMock).delete(policiesBaseUrl() + POLICY_2_ID);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.configuration;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-
-import com.google.common.base.Charsets;
-import com.google.common.io.Resources;
-import com.google.gson.Gson;
-import com.google.gson.JsonIOException;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gson.JsonSyntaxException;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.Map;
-
-import org.junit.jupiter.api.Test;
-import org.oransc.policyagent.exceptions.ServiceException;
-
-class ApplicationConfigParserTest {
-
- ApplicationConfigParser parserUnderTest = new ApplicationConfigParser();
-
- @Test
- void whenCorrectConfig() throws Exception {
- JsonObject jsonRootObject = getJsonRootObject();
-
- ApplicationConfigParser.ConfigParserResult result = parserUnderTest.parse(jsonRootObject);
-
- String topicUrl = result.dmaapProducerTopicUrl();
- assertEquals("http://admin:admin@localhost:6845/events/A1-POLICY-AGENT-WRITE", topicUrl, "controller contents");
-
- topicUrl = result.dmaapConsumerTopicUrl();
- assertEquals(
- "http://admin:admin@localhost:6845/events/A1-POLICY-AGENT-READ/users/policy-agent?timeout=15000&limit=100",
- topicUrl, "controller contents");
-
- Map<String, ControllerConfig> controllers = result.controllerConfigs();
- assertEquals(1, controllers.size(), "size");
- ImmutableControllerConfig expectedControllerConfig = ImmutableControllerConfig.builder() //
- .baseUrl("http://localhost:8083/") //
- .name("controller1") //
- .userName("user") //
- .password("password") //
- .build(); //
- assertEquals(expectedControllerConfig, controllers.get("controller1"), "controller contents");
- }
-
- private JsonObject getJsonRootObject() throws JsonIOException, JsonSyntaxException, IOException {
- JsonObject rootObject = JsonParser.parseReader(new InputStreamReader(getCorrectJson())).getAsJsonObject();
- return rootObject;
- }
-
- private static InputStream getCorrectJson() throws IOException {
- URL url = ApplicationConfigParser.class.getClassLoader()
- .getResource("test_application_configuration_with_dmaap_config.json");
- String string = Resources.toString(url, Charsets.UTF_8);
- return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
- }
-
- @Test
- void whenDmaapConfigHasSeveralStreamsPublishing() throws Exception {
- JsonObject jsonRootObject = getJsonRootObject();
- JsonObject json = jsonRootObject.getAsJsonObject("config").getAsJsonObject("streams_publishes");
- JsonObject fake_info_object = new JsonObject();
- fake_info_object.addProperty("fake_info", "fake");
- json.add("fake_info_object", new Gson().toJsonTree(fake_info_object));
- DataPublishing data = new Gson().fromJson(json.toString(), DataPublishing.class);
- final String expectedMessage =
- "Invalid configuration. Number of streams must be one, config: " + data.toString();
-
- Exception actualException = assertThrows(ServiceException.class, () -> parserUnderTest.parse(jsonRootObject));
-
- assertEquals(expectedMessage, actualException.getMessage(),
- "Wrong error message when the DMaaP config has several streams publishing");
- }
-
- class DataPublishing {
- private JsonObject dmaap_publisher;
- private JsonObject fake_info_object;
-
- @Override
- public String toString() {
- return String.format("[dmaap_publisher=%s, fake_info_object=%s]", dmaap_publisher.toString(),
- fake_info_object.toString());
- }
- }
-
- @Test
- void whenDmaapConfigHasSeveralStreamsSubscribing() throws Exception {
- JsonObject jsonRootObject = getJsonRootObject();
- JsonObject json = jsonRootObject.getAsJsonObject("config").getAsJsonObject("streams_subscribes");
- JsonObject fake_info_object = new JsonObject();
- fake_info_object.addProperty("fake_info", "fake");
- json.add("fake_info_object", new Gson().toJsonTree(fake_info_object));
- DataSubscribing data = new Gson().fromJson(json.toString(), DataSubscribing.class);
- final String expectedMessage =
- "Invalid configuration. Number of streams must be one, config: " + data.toString();
-
- Exception actualException = assertThrows(ServiceException.class, () -> parserUnderTest.parse(jsonRootObject));
-
- assertEquals(expectedMessage, actualException.getMessage(),
- "Wrong error message when the DMaaP config has several streams subscribing");
- }
-
- private class DataSubscribing {
- private JsonObject dmaap_subscriber;
- private JsonObject fake_info_object;
-
- @Override
- public String toString() {
- return String.format("[dmaap_subscriber=%s, fake_info_object=%s]", dmaap_subscriber.toString(),
- fake_info_object.toString());
- }
- }
-
- @Test
- void whenWrongMemberNameInObject() throws Exception {
- JsonObject jsonRootObject = getJsonRootObject();
- JsonObject json = jsonRootObject.getAsJsonObject("config");
- json.remove("ric");
- final String message = "Could not find member: 'ric' in: " + json;
-
- Exception actualException = assertThrows(ServiceException.class, () -> parserUnderTest.parse(jsonRootObject));
-
- assertEquals(message, actualException.getMessage(), "Wrong error message when wrong member name in object");
- }
-
- JsonObject getDmaapInfo(JsonObject jsonRootObject, String streamsPublishesOrSubscribes,
- String dmaapPublisherOrSubscriber) throws Exception {
- return jsonRootObject.getAsJsonObject("config").getAsJsonObject(streamsPublishesOrSubscribes)
- .getAsJsonObject(dmaapPublisherOrSubscriber).getAsJsonObject("dmaap_info");
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.configuration;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNull;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.Vector;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.oransc.policyagent.configuration.ApplicationConfig.RicConfigUpdate;
-import org.oransc.policyagent.configuration.ApplicationConfigParser.ConfigParserResult;
-import org.oransc.policyagent.exceptions.ServiceException;
-
-@ExtendWith(MockitoExtension.class)
-class ApplicationConfigTest {
-
- private static final ImmutableRicConfig RIC_CONFIG_1 = ImmutableRicConfig.builder() //
- .name("ric1") //
- .baseUrl("ric1_url") //
- .managedElementIds(new Vector<>()) //
- .controllerName("") //
- .build();
-
- ConfigParserResult configParserResult(RicConfig... rics) {
- return ImmutableConfigParserResult.builder() //
- .ricConfigs(Arrays.asList(rics)) //
- .dmaapConsumerTopicUrl("dmaapConsumerTopicUrl") //
- .dmaapProducerTopicUrl("dmaapProducerTopicUrl") //
- .controllerConfigs(new HashMap<>()) //
- .build();
- }
-
- @Test
- void gettingNotAddedRicShouldThrowException() {
- ApplicationConfig appConfigUnderTest = new ApplicationConfig();
-
- appConfigUnderTest.setConfiguration(configParserResult(RIC_CONFIG_1));
-
- Exception exception = assertThrows(ServiceException.class, () -> {
- appConfigUnderTest.getRic("name");
- });
-
- assertEquals("Could not find ric configuration: name", exception.getMessage());
- }
-
- @Test
- void addRicShouldNotifyAllObserversOfRicAdded() throws Exception {
- ApplicationConfig appConfigUnderTest = new ApplicationConfig();
-
- RicConfigUpdate update = appConfigUnderTest.setConfiguration(configParserResult(RIC_CONFIG_1)).blockFirst();
- assertEquals(RicConfigUpdate.Type.ADDED, update.getType());
- assertTrue(appConfigUnderTest.getRicConfigs().contains(RIC_CONFIG_1), "Ric not added to configurations.");
-
- assertEquals(RIC_CONFIG_1, appConfigUnderTest.getRic(RIC_CONFIG_1.name()),
- "Not correct Ric retrieved from configurations.");
-
- update = appConfigUnderTest.setConfiguration(configParserResult(RIC_CONFIG_1)).blockFirst();
- assertNull(update, "Nothing should be updated");
- assertTrue(appConfigUnderTest.getRicConfigs().contains(RIC_CONFIG_1), "Ric should remain.");
-
- }
-
- @Test
- void changedRicShouldNotifyAllObserversOfRicChanged() throws Exception {
- ApplicationConfig appConfigUnderTest = new ApplicationConfig();
-
- appConfigUnderTest.setConfiguration(configParserResult(RIC_CONFIG_1));
-
- ImmutableRicConfig changedRicConfig = ImmutableRicConfig.builder() //
- .name("ric1") //
- .baseUrl("changed_ric1_url") //
- .managedElementIds(new Vector<>()) //
- .controllerName("") //
- .build();
-
- RicConfigUpdate update = appConfigUnderTest.setConfiguration(configParserResult(changedRicConfig)).blockFirst();
-
- assertEquals(RicConfigUpdate.Type.CHANGED, update.getType());
- assertEquals(changedRicConfig, appConfigUnderTest.getRic(RIC_CONFIG_1.name()),
- "Changed Ric not retrieved from configurations.");
- }
-
- @Test
- void removedRicShouldNotifyAllObserversOfRicRemoved() {
- ApplicationConfig appConfigUnderTest = new ApplicationConfig();
-
- ImmutableRicConfig ricConfig2 = ImmutableRicConfig.builder() //
- .name("ric2") //
- .baseUrl("ric2_url") //
- .managedElementIds(new Vector<>()) //
- .controllerName("") //
- .build();
-
- appConfigUnderTest.setConfiguration(configParserResult(RIC_CONFIG_1, ricConfig2));
-
- RicConfigUpdate update = appConfigUnderTest.setConfiguration(configParserResult(ricConfig2)).blockFirst();
-
- assertEquals(RicConfigUpdate.Type.REMOVED, update.getType());
- assertEquals(1, appConfigUnderTest.getRicConfigs().size(), "Ric not deleted from configurations.");
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.dmaap;
-
-import static ch.qos.logback.classic.Level.WARN;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.inOrder;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.read.ListAppender;
-
-import java.time.Duration;
-import java.util.LinkedList;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.ArgumentCaptor;
-import org.mockito.InOrder;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.oransc.policyagent.clients.AsyncRestClient;
-import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.utils.LoggingUtils;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import reactor.core.publisher.Mono;
-
-@ExtendWith(MockitoExtension.class)
-class DmaapMessageConsumerTest {
- @Mock
- private ApplicationConfig applicationConfigMock;
- @Mock
- private AsyncRestClient messageRouterConsumerMock;
- @Mock
- private DmaapMessageHandler messageHandlerMock;
-
- private DmaapMessageConsumer messageConsumerUnderTest;
-
- @AfterEach
- void resetLogging() {
- LoggingUtils.getLogListAppender(DmaapMessageConsumer.class);
- }
-
- @Test
- void dmaapNotConfigured_thenSleepAndRetryUntilConfig() throws Exception {
- messageConsumerUnderTest = spy(new DmaapMessageConsumer(applicationConfigMock));
-
- doNothing().when(messageConsumerUnderTest).sleep(any(Duration.class));
- doReturn(false, false, false, true).when(messageConsumerUnderTest).isStopped();
- doReturn(false, true, true).when(messageConsumerUnderTest).isDmaapConfigured();
- doReturn(new LinkedList<>()).when(messageConsumerUnderTest).fetchAllMessages();
-
- messageConsumerUnderTest.start().join();
-
- InOrder orderVerifier = inOrder(messageConsumerUnderTest);
- orderVerifier.verify(messageConsumerUnderTest).sleep(DmaapMessageConsumer.TIME_BETWEEN_DMAAP_RETRIES);
- orderVerifier.verify(messageConsumerUnderTest).fetchAllMessages();
- }
-
- @Test
- void dmaapConfigurationRemoved_thenStopPollingDmaapSleepAndRetry() throws Exception {
- messageConsumerUnderTest = spy(new DmaapMessageConsumer(applicationConfigMock));
-
- doNothing().when(messageConsumerUnderTest).sleep(any(Duration.class));
- doReturn(false, false, false, false, true).when(messageConsumerUnderTest).isStopped();
- doReturn(true, true, false).when(messageConsumerUnderTest).isDmaapConfigured();
- doReturn(new LinkedList<>()).when(messageConsumerUnderTest).fetchAllMessages();
-
- messageConsumerUnderTest.start().join();
-
- InOrder orderVerifier = inOrder(messageConsumerUnderTest);
- orderVerifier.verify(messageConsumerUnderTest).fetchAllMessages();
- orderVerifier.verify(messageConsumerUnderTest).sleep(DmaapMessageConsumer.TIME_BETWEEN_DMAAP_RETRIES);
- }
-
- @Test
- void dmaapConfiguredAndNoMessages_thenPollOnce() throws Exception {
- setUpMrConfig();
-
- messageConsumerUnderTest = spy(new DmaapMessageConsumer(applicationConfigMock));
-
- Mono<ResponseEntity<String>> response = Mono.empty();
-
- doReturn(false, true).when(messageConsumerUnderTest).isStopped();
- doReturn(messageRouterConsumerMock).when(messageConsumerUnderTest).getMessageRouterConsumer();
- doReturn(response).when(messageRouterConsumerMock).getForEntity(any());
-
- messageConsumerUnderTest.start().join();
-
- verify(messageRouterConsumerMock).getForEntity(any());
- verifyNoMoreInteractions(messageRouterConsumerMock);
- }
-
- @Test
- void dmaapConfiguredAndErrorGettingMessages_thenLogWarningAndSleep() throws Exception {
- setUpMrConfig();
-
- messageConsumerUnderTest = spy(new DmaapMessageConsumer(applicationConfigMock));
-
- doNothing().when(messageConsumerUnderTest).sleep(any(Duration.class));
- doReturn(false, true).when(messageConsumerUnderTest).isStopped();
- doReturn(messageRouterConsumerMock).when(messageConsumerUnderTest).getMessageRouterConsumer();
-
- Mono<ResponseEntity<String>> response = Mono.just(new ResponseEntity<>("Error", HttpStatus.BAD_REQUEST));
- when(messageRouterConsumerMock.getForEntity(any())).thenReturn(response);
-
- final ListAppender<ILoggingEvent> logAppender =
- LoggingUtils.getLogListAppender(DmaapMessageConsumer.class, WARN);
-
- messageConsumerUnderTest.start().join();
-
- assertThat(logAppender.list.get(0).getFormattedMessage())
- .isEqualTo("Cannot fetch because of Error respons: 400 BAD_REQUEST Error");
-
- verify(messageConsumerUnderTest).sleep(DmaapMessageConsumer.TIME_BETWEEN_DMAAP_RETRIES);
- }
-
- @Test
- void dmaapConfiguredAndOneMessage_thenPollOnceAndProcessMessage() throws Exception {
- // The message from MR is here an array of Json objects
- setUpMrConfig();
- messageConsumerUnderTest = spy(new DmaapMessageConsumer(applicationConfigMock));
-
- String message = "{\"apiVersion\":\"1.0\"," //
- + "\"operation\":\"GET\"," //
- + "\"correlationId\":\"1592341013115594000\"," //
- + "\"originatorId\":\"849e6c6b420\"," //
- + "\"payload\":{}," //
- + "\"requestId\":\"23343221\", " //
- + "\"target\":\"policy-agent\"," //
- + "\"timestamp\":\"2020-06-16 20:56:53.115665\"," //
- + "\"type\":\"request\"," //
- + "\"url\":\"/rics\"}";
- String messages = "[" + message + "]";
-
- doReturn(false, true).when(messageConsumerUnderTest).isStopped();
- doReturn(messageRouterConsumerMock).when(messageConsumerUnderTest).getMessageRouterConsumer();
-
- Mono<ResponseEntity<String>> response = Mono.just(new ResponseEntity<>(messages, HttpStatus.OK));
- when(messageRouterConsumerMock.getForEntity(any())).thenReturn(response);
-
- doReturn(messageHandlerMock).when(messageConsumerUnderTest).getDmaapMessageHandler();
-
- messageConsumerUnderTest.start().join();
-
- ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
- verify(messageHandlerMock).handleDmaapMsg(captor.capture());
- String messageAfterJsonParsing = captor.getValue();
- assertThat(messageAfterJsonParsing).contains("apiVersion");
-
- verifyNoMoreInteractions(messageHandlerMock);
- }
-
- @Test
- void dmaapConfiguredAndOneMessage_thenPollOnceAndProcessMessage2() throws Exception {
- // The message from MR is here an array of String (which is the case when the MR
- // simulator is used)
- setUpMrConfig();
- messageConsumerUnderTest = spy(new DmaapMessageConsumer(applicationConfigMock));
-
- doReturn(false, true).when(messageConsumerUnderTest).isStopped();
- doReturn(messageRouterConsumerMock).when(messageConsumerUnderTest).getMessageRouterConsumer();
-
- Mono<ResponseEntity<String>> response = Mono.just(new ResponseEntity<>("[\"aMessage\"]", HttpStatus.OK));
- when(messageRouterConsumerMock.getForEntity(any())).thenReturn(response);
-
- doReturn(messageHandlerMock).when(messageConsumerUnderTest).getDmaapMessageHandler();
-
- messageConsumerUnderTest.start().join();
-
- verify(messageHandlerMock).handleDmaapMsg("aMessage");
- verifyNoMoreInteractions(messageHandlerMock);
- }
-
- private void setUpMrConfig() {
- when(applicationConfigMock.getDmaapConsumerTopicUrl()).thenReturn("url");
- when(applicationConfigMock.getDmaapProducerTopicUrl()).thenReturn("url");
- }
-}
+++ /dev/null
-/*-
- * ============LICENSE_START=======================================================
- * Copyright (C) 2019 Nordix Foundation.
- * ================================================================================
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- * SPDX-License-Identifier: Apache-2.0
- * ============LICENSE_END=========================================================
- */
-
-package org.oransc.policyagent.dmaap;
-
-import static ch.qos.logback.classic.Level.WARN;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNotNull;
-import static org.junit.jupiter.api.Assertions.assertTrue;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.read.ListAppender;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-import com.google.gson.JsonObject;
-
-import java.io.IOException;
-import java.nio.charset.Charset;
-import java.util.Optional;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.mockito.ArgumentCaptor;
-import org.oransc.policyagent.clients.AsyncRestClient;
-import org.oransc.policyagent.dmaap.DmaapRequestMessage.Operation;
-import org.oransc.policyagent.repository.ImmutablePolicyType;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.utils.LoggingUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-
-class DmaapMessageHandlerTest {
- private static final Logger logger = LoggerFactory.getLogger(DmaapMessageHandlerTest.class);
- private static final String URL = "url";
-
- private final AsyncRestClient dmaapClient = mock(AsyncRestClient.class);
- private final AsyncRestClient agentClient = mock(AsyncRestClient.class);
- private DmaapMessageHandler testedObject;
- private static Gson gson = new GsonBuilder() //
- .create(); //
-
- @BeforeEach
- private void setUp() throws Exception {
- testedObject = spy(new DmaapMessageHandler(dmaapClient, agentClient));
- }
-
- static JsonObject payloadAsJson() {
- return gson.fromJson(payloadAsString(), JsonObject.class);
- }
-
- static String payloadAsString() {
- PolicyType pt = ImmutablePolicyType.builder().name("name").schema("schema").build();
- return gson.toJson(pt);
- }
-
- DmaapRequestMessage dmaapRequestMessage(Operation operation) {
- Optional<JsonObject> payload =
- ((operation == Operation.PUT || operation == Operation.POST) ? Optional.of(payloadAsJson())
- : Optional.empty());
- return ImmutableDmaapRequestMessage.builder() //
- .apiVersion("apiVersion") //
- .correlationId("correlationId") //
- .operation(operation) //
- .originatorId("originatorId") //
- .payload(payload) //
- .requestId("requestId") //
- .target("target") //
- .timestamp("timestamp") //
- .url(URL) //
- .build();
- }
-
- private String dmaapInputMessage(Operation operation) {
- return gson.toJson(dmaapRequestMessage(operation));
- }
-
- private Mono<ResponseEntity<String>> okResponse() {
- ResponseEntity<String> entity = new ResponseEntity<>("OK", HttpStatus.OK);
- return Mono.just(entity);
- }
-
- private Mono<ResponseEntity<String>> notOkResponse() {
- ResponseEntity<String> entity = new ResponseEntity<>("NOK", HttpStatus.BAD_GATEWAY);
- return Mono.just(entity);
- }
-
- @Test
- void testMessageParsing() {
- String message = dmaapInputMessage(Operation.DELETE);
- logger.info(message);
- DmaapRequestMessage parsedMessage = gson.fromJson(message, ImmutableDmaapRequestMessage.class);
- assertNotNull(parsedMessage);
- assertFalse(parsedMessage.payload().isPresent());
-
- message = dmaapInputMessage(Operation.PUT);
- logger.info(message);
- parsedMessage = gson.fromJson(message, ImmutableDmaapRequestMessage.class);
- assertNotNull(parsedMessage);
- assertTrue(parsedMessage.payload().isPresent());
- }
-
- @Test
- void unparseableMessage_thenWarning() {
- final ListAppender<ILoggingEvent> logAppender =
- LoggingUtils.getLogListAppender(DmaapMessageHandler.class, WARN);
-
- String msg = "bad message";
- testedObject.handleDmaapMsg(msg);
-
- assertThat(logAppender.list.get(0).getFormattedMessage()).startsWith(
- "handleDmaapMsg failure org.oransc.policyagent.exceptions.ServiceException: Received unparsable "
- + "message from DMAAP: \"" + msg + "\", reason: ");
- }
-
- @Test
- void successfulDelete() throws IOException {
- doReturn(okResponse()).when(agentClient).deleteForEntity(anyString());
- doReturn(Mono.just("OK")).when(dmaapClient).post(anyString(), anyString());
-
- String message = dmaapInputMessage(Operation.DELETE);
-
- StepVerifier //
- .create(testedObject.createTask(message)) //
- .expectSubscription() //
- .expectNext("OK") //
- .verifyComplete(); //
-
- verify(agentClient).deleteForEntity(URL);
- verifyNoMoreInteractions(agentClient);
-
- verify(dmaapClient).post(anyString(), anyString());
-
- verifyNoMoreInteractions(dmaapClient);
- }
-
- @Test
- void successfulGet() throws IOException {
- doReturn(okResponse()).when(agentClient).getForEntity(anyString());
- doReturn(Mono.just("OK")).when(dmaapClient).post(anyString(), anyString());
-
- StepVerifier //
- .create(testedObject.createTask(dmaapInputMessage(Operation.GET))) //
- .expectSubscription() //
- .expectNext("OK") //
- .verifyComplete(); //
-
- verify(agentClient).getForEntity(URL);
- verifyNoMoreInteractions(agentClient);
-
- verify(dmaapClient).post(anyString(), anyString());
- verifyNoMoreInteractions(dmaapClient);
- }
-
- @Test
- void exceptionFromAgentWhenGet_thenPostError() throws IOException {
- String errorBody = "Unavailable";
- WebClientResponseException webClientResponseException = new WebClientResponseException(
- HttpStatus.SERVICE_UNAVAILABLE.value(), "", (HttpHeaders) null, errorBody.getBytes(), (Charset) null);
- doReturn(Mono.error(webClientResponseException)).when(agentClient).getForEntity(anyString());
- doReturn(Mono.just("OK")).when(dmaapClient).post(anyString(), anyString());
-
- StepVerifier //
- .create(testedObject.createTask(dmaapInputMessage(Operation.GET))) //
- .expectSubscription() //
- .verifyComplete(); //
-
- ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
- verify(dmaapClient).post(anyString(), captor.capture());
- String actualMessage = captor.getValue();
- assertThat(actualMessage).contains(HttpStatus.SERVICE_UNAVAILABLE.toString()) //
- .contains(errorBody);
- }
-
- @Test
- void successfulPut() throws IOException {
- doReturn(okResponse()).when(agentClient).putForEntity(anyString(), anyString());
- doReturn(Mono.just("OK")).when(dmaapClient).post(anyString(), anyString());
-
- StepVerifier //
- .create(testedObject.createTask(dmaapInputMessage(Operation.PUT))) //
- .expectSubscription() //
- .expectNext("OK") //
- .verifyComplete(); //
-
- verify(agentClient).putForEntity(URL, payloadAsString());
- verifyNoMoreInteractions(agentClient);
-
- verify(dmaapClient).post(anyString(), anyString());
- verifyNoMoreInteractions(dmaapClient);
- }
-
- @Test
- void successfulPost() throws IOException {
- doReturn(okResponse()).when(agentClient).postForEntity(anyString(), anyString());
- doReturn(Mono.just("OK")).when(dmaapClient).post(anyString(), anyString());
-
- StepVerifier //
- .create(testedObject.createTask(dmaapInputMessage(Operation.POST))) //
- .expectSubscription() //
- .expectNext("OK") //
- .verifyComplete(); //
-
- verify(agentClient).postForEntity(URL, payloadAsString());
- verifyNoMoreInteractions(agentClient);
-
- verify(dmaapClient).post(anyString(), anyString());
- verifyNoMoreInteractions(dmaapClient);
- }
-
- @Test
- void exceptionWhenCallingPolicyAgent_thenNotFoundResponse() throws IOException {
-
- doReturn(notOkResponse()).when(agentClient).putForEntity(anyString(), anyString());
- doReturn(Mono.just("OK")).when(dmaapClient).post(anyString(), anyString());
-
- testedObject.createTask(dmaapInputMessage(Operation.PUT)).block();
-
- verify(agentClient).putForEntity(anyString(), anyString());
- verifyNoMoreInteractions(agentClient);
-
- ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
- verify(dmaapClient).post(anyString(), captor.capture());
- String actualMessage = captor.getValue();
- assertThat(actualMessage).as("Message \"%s\" sent to DMaaP contains %s", actualMessage, HttpStatus.BAD_GATEWAY)
- .contains(HttpStatus.BAD_GATEWAY.toString());
-
- verifyNoMoreInteractions(dmaapClient);
- }
-
- @Test
- void unsupportedOperationInMessage_thenNotFoundResponseWithNotImplementedOperation() throws Exception {
- String message = dmaapInputMessage(Operation.PUT).toString();
- String badOperation = "BAD";
- message = message.replace(Operation.PUT.toString(), badOperation);
-
- testedObject.handleDmaapMsg(message);
-
- ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
- verify(dmaapClient).post(anyString(), captor.capture());
- String actualMessage = captor.getValue();
- assertThat(actualMessage).contains("Not implemented operation") //
- .contains("BAD_REQUEST");
- }
-
- @Test
- void putWithoutPayload_thenNotFoundResponseWithWarning() throws Exception {
- String message = dmaapInputMessage(Operation.PUT).toString();
- message = message.replace(",\"payload\":{\"name\":\"name\",\"schema\":\"schema\"}", "");
-
- final ListAppender<ILoggingEvent> logAppender =
- LoggingUtils.getLogListAppender(DmaapMessageHandler.class, WARN);
-
- testedObject.handleDmaapMsg(message);
-
- assertThat(logAppender.list.get(0).getFormattedMessage())
- .startsWith("Expected payload in message from DMAAP: ");
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.repository;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-import java.io.IOException;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.oransc.policyagent.exceptions.ServiceException;
-import org.oransc.policyagent.repository.Lock.LockType;
-
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-
-@ExtendWith(MockitoExtension.class)
-class LockTest {
-
- @SuppressWarnings("squid:S2925") // "Thread.sleep" should not be used in tests.
- private void sleep() {
- try {
- Thread.sleep(100);
- } catch (InterruptedException e) {
- // Do nothing.
- }
- }
-
- private void asynchUnlock(Lock lock) {
- Thread thread = new Thread(() -> {
- sleep();
- lock.unlockBlocking();
- });
- thread.start();
- }
-
- @Test
- void testLock() throws IOException, ServiceException {
- Lock lock = new Lock();
- lock.lockBlocking(LockType.SHARED);
- lock.unlockBlocking();
-
- lock.lockBlocking(LockType.EXCLUSIVE);
- asynchUnlock(lock);
-
- lock.lockBlocking(LockType.SHARED);
- lock.unlockBlocking();
-
- assertThat(lock.getLockCounter()).isZero();
- }
-
- @Test
- void testReactiveLock() {
- Lock lock = new Lock();
-
- Mono<Lock> seq = lock.lock(LockType.EXCLUSIVE) //
- .flatMap(l -> lock.lock(LockType.EXCLUSIVE)) //
- .flatMap(l -> lock.unlock());
-
- asynchUnlock(lock);
- StepVerifier.create(seq) //
- .expectSubscription() //
- .expectNext(lock) //
- .verifyComplete();
-
- assertThat(lock.getLockCounter()).isZero();
-
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.tasks;
-
-import static ch.qos.logback.classic.Level.WARN;
-import static org.assertj.core.api.Assertions.assertThat;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.read.ListAppender;
-
-import java.util.Properties;
-
-import org.junit.jupiter.api.Test;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.EnvProperties;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.ImmutableEnvProperties;
-import org.oransc.policyagent.exceptions.EnvironmentLoaderException;
-import org.oransc.policyagent.utils.LoggingUtils;
-import reactor.test.StepVerifier;
-
-class EnvironmentProcessorTest {
- private static final String CONSUL_HOST = "CONSUL_HOST";
- private static final String CONSUL_HOST_VALUE = "consulHost";
-
- private static final String CONFIG_BINDING_SERVICE = "CONFIG_BINDING_SERVICE";
- private static final String CONFIG_BINDING_SERVICE_VALUE = "configBindingService";
-
- private static final String HOSTNAME = "HOSTNAME";
- private static final String HOSTNAME_VALUE = "hostname";
-
- @Test
- void allPropertiesAvailableWithHostname_thenAllPropertiesAreReturnedWithGivenConsulPort() {
- Properties systemEnvironment = new Properties();
- String consulPort = "8080";
- systemEnvironment.put(CONSUL_HOST, CONSUL_HOST_VALUE);
- systemEnvironment.put("CONSUL_PORT", consulPort);
- systemEnvironment.put(CONFIG_BINDING_SERVICE, CONFIG_BINDING_SERVICE_VALUE);
- systemEnvironment.put(HOSTNAME, HOSTNAME_VALUE);
-
- EnvProperties expectedEnvProperties = ImmutableEnvProperties.builder() //
- .consulHost(CONSUL_HOST_VALUE) //
- .consulPort(Integer.valueOf(consulPort)) //
- .cbsName(CONFIG_BINDING_SERVICE_VALUE) //
- .appName(HOSTNAME_VALUE) //
- .build();
-
- StepVerifier.create(EnvironmentProcessor.readEnvironmentVariables(systemEnvironment))
- .expectNext(expectedEnvProperties).expectComplete();
- }
-
- @Test
- void consulHostMissing_thenExceptionReturned() {
- Properties systemEnvironment = new Properties();
-
- StepVerifier.create(EnvironmentProcessor.readEnvironmentVariables(systemEnvironment))
- .expectErrorMatches(throwable -> throwable instanceof EnvironmentLoaderException
- && throwable.getMessage().equals("$CONSUL_HOST environment has not been defined"))
- .verify();
- }
-
- @Test
- void withAllPropertiesExceptConsulPort_thenAllPropertiesAreReturnedWithDefaultConsulPortAndWarning() {
- Properties systemEnvironment = new Properties();
- systemEnvironment.put(CONSUL_HOST, CONSUL_HOST_VALUE);
- systemEnvironment.put(CONFIG_BINDING_SERVICE, CONFIG_BINDING_SERVICE_VALUE);
- systemEnvironment.put(HOSTNAME, HOSTNAME_VALUE);
-
- String defaultConsulPort = "8500";
- EnvProperties expectedEnvProperties = ImmutableEnvProperties.builder() //
- .consulHost(CONSUL_HOST_VALUE) //
- .consulPort(Integer.valueOf(defaultConsulPort)) //
- .cbsName(CONFIG_BINDING_SERVICE_VALUE) //
- .appName(HOSTNAME_VALUE) //
- .build();
-
- final ListAppender<ILoggingEvent> logAppender =
- LoggingUtils.getLogListAppender(EnvironmentProcessor.class, WARN);
-
- StepVerifier.create(EnvironmentProcessor.readEnvironmentVariables(systemEnvironment))
- .expectNext(expectedEnvProperties).expectComplete();
-
- assertThat(logAppender.list.get(0).getFormattedMessage())
- .isEqualTo("$CONSUL_PORT variable will be set to default port " + defaultConsulPort);
- }
-
- @Test
- void configBindingServiceMissing_thenExceptionReturned() {
- Properties systemEnvironment = new Properties();
- systemEnvironment.put(CONSUL_HOST, CONSUL_HOST_VALUE);
-
- StepVerifier.create(EnvironmentProcessor.readEnvironmentVariables(systemEnvironment))
- .expectErrorMatches(throwable -> throwable instanceof EnvironmentLoaderException
- && throwable.getMessage().equals("$CONFIG_BINDING_SERVICE environment has not been defined"))
- .verify();
- }
-
- @Test
- void allPropertiesAvailableWithServiceName_thenAllPropertiesAreReturned() {
- Properties systemEnvironment = new Properties();
- String consulPort = "8080";
- systemEnvironment.put(CONSUL_HOST, CONSUL_HOST_VALUE);
- systemEnvironment.put("CONSUL_PORT", consulPort);
- systemEnvironment.put(CONFIG_BINDING_SERVICE, CONFIG_BINDING_SERVICE_VALUE);
- systemEnvironment.put("SERVICE_NAME", HOSTNAME_VALUE);
-
- EnvProperties expectedEnvProperties = ImmutableEnvProperties.builder() //
- .consulHost(CONSUL_HOST_VALUE) //
- .consulPort(Integer.valueOf(consulPort)) //
- .cbsName(CONFIG_BINDING_SERVICE_VALUE) //
- .appName(HOSTNAME_VALUE) //
- .build();
-
- StepVerifier.create(EnvironmentProcessor.readEnvironmentVariables(systemEnvironment))
- .expectNext(expectedEnvProperties).expectComplete();
- }
-
- @Test
- void serviceNameAndHostnameMissing_thenExceptionIsReturned() {
- Properties systemEnvironment = new Properties();
- systemEnvironment.put(CONSUL_HOST, CONSUL_HOST_VALUE);
- systemEnvironment.put(CONFIG_BINDING_SERVICE, CONFIG_BINDING_SERVICE_VALUE);
-
- StepVerifier.create(EnvironmentProcessor.readEnvironmentVariables(systemEnvironment))
- .expectErrorMatches(throwable -> throwable instanceof EnvironmentLoaderException && throwable.getMessage()
- .equals("Neither $HOSTNAME/$SERVICE_NAME have not been defined as system environment"))
- .verify();
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.tasks;
-
-import static ch.qos.logback.classic.Level.ERROR;
-import static ch.qos.logback.classic.Level.WARN;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Awaitility.await;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doNothing;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.read.ListAppender;
-
-import com.google.common.base.Charsets;
-import com.google.common.io.Resources;
-import com.google.gson.JsonIOException;
-import com.google.gson.JsonObject;
-import com.google.gson.JsonParser;
-import com.google.gson.JsonSyntaxException;
-
-import java.io.ByteArrayInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.time.Duration;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.Properties;
-import java.util.Vector;
-
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.Spy;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.api.CbsClient;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.EnvProperties;
-import org.onap.dcaegen2.services.sdk.rest.services.cbs.client.model.ImmutableEnvProperties;
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.configuration.ApplicationConfig.RicConfigUpdate.Type;
-import org.oransc.policyagent.configuration.ApplicationConfigParser;
-import org.oransc.policyagent.configuration.ApplicationConfigParser.ConfigParserResult;
-import org.oransc.policyagent.configuration.ImmutableConfigParserResult;
-import org.oransc.policyagent.configuration.ImmutableRicConfig;
-import org.oransc.policyagent.configuration.RicConfig;
-import org.oransc.policyagent.repository.ImmutablePolicy;
-import org.oransc.policyagent.repository.ImmutablePolicyType;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Rics;
-import org.oransc.policyagent.repository.Services;
-import org.oransc.policyagent.utils.LoggingUtils;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-import reactor.test.StepVerifier;
-
-@ExtendWith(MockitoExtension.class)
-class RefreshConfigTaskTest {
-
- private static final boolean CONFIG_FILE_EXISTS = true;
- private static final boolean CONFIG_FILE_DOES_NOT_EXIST = false;
-
- private RefreshConfigTask refreshTaskUnderTest;
-
- @Spy
- ApplicationConfig appConfig;
-
- @Mock
- CbsClient cbsClient;
-
- private static final String RIC_1_NAME = "ric1";
- private static final ImmutableRicConfig CORRECT_RIC_CONIFG = ImmutableRicConfig.builder() //
- .name(RIC_1_NAME) //
- .baseUrl("http://localhost:8080/") //
- .managedElementIds(new Vector<String>(Arrays.asList("kista_1", "kista_2"))) //
- .controllerName("") //
- .build();
-
- private static EnvProperties properties() {
- return ImmutableEnvProperties.builder() //
- .consulHost("host") //
- .consulPort(123) //
- .cbsName("cbsName") //
- .appName("appName") //
- .build();
- }
-
- private RefreshConfigTask createTestObject(boolean configFileExists) {
- return createTestObject(configFileExists, new Rics(), new Policies(), true);
- }
-
- private RefreshConfigTask createTestObject(boolean configFileExists, Rics rics, Policies policies,
- boolean stubConfigFileExists) {
- RefreshConfigTask obj = spy(new RefreshConfigTask(appConfig, rics, policies, new Services(), new PolicyTypes(),
- new A1ClientFactory(appConfig)));
- if (stubConfigFileExists) {
- doReturn(configFileExists).when(obj).fileExists(any());
- }
- return obj;
- }
-
- @Test
- void startWithStubbedRefresh_thenTerminationLogged() {
- refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST, null, null, false);
- doReturn(Flux.empty()).when(refreshTaskUnderTest).createRefreshTask();
-
- final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class, ERROR);
-
- refreshTaskUnderTest.start();
-
- assertThat(logAppender.list.get(0).getFormattedMessage()).isEqualTo("Configuration refresh terminated");
- }
-
- @Test
- void startWithStubbedRefreshReturnError_thenErrorAndTerminationLogged() {
- refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST, null, null, false);
- String errorMessage = "Error";
- doReturn(Flux.error(new Exception(errorMessage))).when(refreshTaskUnderTest).createRefreshTask();
-
- final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class, ERROR);
-
- refreshTaskUnderTest.start();
-
- ILoggingEvent event = logAppender.list.get(0);
- assertThat(event.getFormattedMessage())
- .isEqualTo("Configuration refresh terminated due to exception java.lang.Exception: " + errorMessage);
- }
-
- @Test
- void stop_thenTaskIsDisposed() throws Exception {
- refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST, null, null, false);
- refreshTaskUnderTest.systemEnvironment = new Properties();
-
- refreshTaskUnderTest.start();
- refreshTaskUnderTest.stop();
-
- assertThat(refreshTaskUnderTest.getRefreshTask().isDisposed()).as("Refresh task is disposed").isTrue();
- }
-
- @Test
- void whenTheConfigurationFits_thenConfiguredRicsArePutInRepository() throws Exception {
- refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_EXISTS);
- refreshTaskUnderTest.systemEnvironment = new Properties();
- // When
- doReturn(getCorrectJson()).when(refreshTaskUnderTest).createInputStream(any());
- doReturn("fileName").when(appConfig).getLocalConfigurationFilePath();
-
- StepVerifier //
- .create(refreshTaskUnderTest.createRefreshTask()) //
- .expectSubscription() //
- .expectNext(Type.ADDED) //
- .expectNext(Type.ADDED) //
- .thenCancel() //
- .verify();
-
- // Then
- verify(refreshTaskUnderTest).loadConfigurationFromFile();
-
- verify(refreshTaskUnderTest, times(2)).runRicSynchronization(any(Ric.class));
-
- Iterable<RicConfig> ricConfigs = appConfig.getRicConfigs();
- RicConfig ricConfig = ricConfigs.iterator().next();
- assertThat(ricConfigs).isNotNull();
- assertThat(ricConfig).isEqualTo(CORRECT_RIC_CONIFG);
- }
-
- @Test
- void whenFileExistsButJsonIsIncorrect_thenNoRicsArePutInRepositoryAndErrorIsLogged() throws Exception {
- refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_EXISTS);
- refreshTaskUnderTest.systemEnvironment = new Properties();
-
- // When
- doReturn(getIncorrectJson()).when(refreshTaskUnderTest).createInputStream(any());
- doReturn("fileName").when(appConfig).getLocalConfigurationFilePath();
-
- final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class, ERROR);
-
- StepVerifier //
- .create(refreshTaskUnderTest.createRefreshTask()) //
- .expectSubscription() //
- .expectNoEvent(Duration.ofMillis(100)) //
- .thenCancel() //
- .verify();
-
- // Then
- verify(refreshTaskUnderTest).loadConfigurationFromFile();
- assertThat(appConfig.getRicConfigs()).isEmpty();
-
- await().until(() -> logAppender.list.size() > 0);
- assertThat(logAppender.list.get(0).getFormattedMessage())
- .startsWith("Local configuration file not loaded: fileName, ");
- }
-
- @Test
- void whenPeriodicConfigRefreshNoConsul_thenErrorIsLogged() {
- refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST);
- refreshTaskUnderTest.systemEnvironment = new Properties();
-
- EnvProperties props = properties();
- doReturn(Mono.just(props)).when(refreshTaskUnderTest).getEnvironment(any());
-
- doReturn(Mono.just(cbsClient)).when(refreshTaskUnderTest).createCbsClient(props);
- when(cbsClient.get(any())).thenReturn(Mono.error(new IOException()));
-
- final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class, WARN);
-
- StepVerifier //
- .create(refreshTaskUnderTest.createRefreshTask()) //
- .expectSubscription() //
- .expectNoEvent(Duration.ofMillis(1000)) //
- .thenCancel() //
- .verify();
-
- await().until(() -> logAppender.list.size() > 0);
- assertThat(logAppender.list.get(0).getFormattedMessage())
- .isEqualTo("Could not refresh application configuration. java.io.IOException");
- }
-
- @Test
- void whenPeriodicConfigRefreshSuccess_thenNewConfigIsCreatedAndRepositoryUpdated() throws Exception {
- Rics rics = new Rics();
- Policies policies = new Policies();
- refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST, rics, policies, false);
- refreshTaskUnderTest.systemEnvironment = new Properties();
-
- RicConfig changedRicConfig = getRicConfig(RIC_1_NAME);
- rics.put(new Ric(changedRicConfig));
- RicConfig removedRicConfig = getRicConfig("removed");
- Ric removedRic = new Ric(removedRicConfig);
- rics.put(removedRic);
- appConfig.setConfiguration(configParserResult(changedRicConfig, removedRicConfig));
-
- Policy policy = getPolicy(removedRic);
- policies.put(policy);
-
- EnvProperties props = properties();
- doReturn(Mono.just(props)).when(refreshTaskUnderTest).getEnvironment(any());
- doReturn(Mono.just(cbsClient)).when(refreshTaskUnderTest).createCbsClient(props);
-
- JsonObject configAsJson = getJsonRootObject(true);
- String newBaseUrl = "newBaseUrl";
- modifyTheRicConfiguration(configAsJson, newBaseUrl);
- when(cbsClient.get(any())).thenReturn(Mono.just(configAsJson));
- doNothing().when(refreshTaskUnderTest).runRicSynchronization(any(Ric.class));
-
- StepVerifier //
- .create(refreshTaskUnderTest.createRefreshTask()) //
- .expectSubscription() //
- .expectNext(Type.CHANGED) //
- .expectNext(Type.ADDED) //
- .expectNext(Type.REMOVED) //
- .thenCancel() //
- .verify();
-
- assertThat(appConfig.getRicConfigs()).hasSize(2);
- assertThat(appConfig.getRic(RIC_1_NAME).baseUrl()).isEqualTo(newBaseUrl);
- String ric2Name = "ric2";
- assertThat(appConfig.getRic(ric2Name)).isNotNull();
-
- assertThat(rics.size()).isEqualTo(2);
- assertThat(rics.get(RIC_1_NAME).getConfig().baseUrl()).isEqualTo(newBaseUrl);
- assertThat(rics.get(ric2Name)).isNotNull();
-
- assertThat(policies.size()).isZero();
- }
-
- @Test
- void whenPeriodicConfigRefreshInvalidJson_thenErrorIsLogged() throws Exception {
- Rics rics = new Rics();
- Policies policies = new Policies();
- refreshTaskUnderTest = this.createTestObject(CONFIG_FILE_DOES_NOT_EXIST, rics, policies, false);
- refreshTaskUnderTest.systemEnvironment = new Properties();
-
- appConfig.setConfiguration(configParserResult());
-
- EnvProperties props = properties();
- doReturn(Mono.just(props)).when(refreshTaskUnderTest).getEnvironment(any());
- doReturn(Mono.just(cbsClient)).when(refreshTaskUnderTest).createCbsClient(props);
-
- JsonObject configAsJson = getJsonRootObject(false);
- when(cbsClient.get(any())).thenReturn(Mono.just(configAsJson));
-
- final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(RefreshConfigTask.class, ERROR);
-
- StepVerifier //
- .create(refreshTaskUnderTest.createRefreshTask()) //
- .expectSubscription() //
- .expectNoEvent(Duration.ofMillis(1000)) //
- .thenCancel() //
- .verify();
-
- await().until(() -> logAppender.list.size() > 0);
- assertThat(logAppender.list.get(0).getFormattedMessage())
- .startsWith("Could not parse configuration org.oransc.policyagent.exceptions.ServiceException: ");
- }
-
- private RicConfig getRicConfig(String name) {
- RicConfig ricConfig = ImmutableRicConfig.builder() //
- .name(name) //
- .baseUrl("url") //
- .managedElementIds(Collections.emptyList()) //
- .controllerName("controllerName") //
- .build();
- return ricConfig;
- }
-
- private Policy getPolicy(Ric ric) {
- ImmutablePolicyType type = ImmutablePolicyType.builder() //
- .name("type") //
- .schema("{}") //
- .build();
- Policy policy = ImmutablePolicy.builder() //
- .id("id") //
- .type(type) //
- .lastModified("lastModified") //
- .ric(ric) //
- .json("{}") //
- .ownerServiceName("ownerServiceName") //
- .isTransient(false) //
- .build();
- return policy;
- }
-
- ConfigParserResult configParserResult(RicConfig... rics) {
- return ImmutableConfigParserResult.builder() //
- .ricConfigs(Arrays.asList(rics)) //
- .dmaapConsumerTopicUrl("") //
- .dmaapProducerTopicUrl("") //
- .controllerConfigs(new HashMap<>()) //
- .build();
- }
-
- private void modifyTheRicConfiguration(JsonObject configAsJson, String newBaseUrl) {
- ((JsonObject) configAsJson.getAsJsonObject("config") //
- .getAsJsonArray("ric").get(0)) //
- .addProperty("baseUrl", newBaseUrl);
- }
-
- private JsonObject getJsonRootObject(boolean valid) throws JsonIOException, JsonSyntaxException, IOException {
- JsonObject rootObject = JsonParser
- .parseReader(new InputStreamReader(valid ? getCorrectJson() : getIncorrectJson())).getAsJsonObject();
- return rootObject;
- }
-
- private static InputStream getCorrectJson() throws IOException {
- URL url = ApplicationConfigParser.class.getClassLoader().getResource("test_application_configuration.json");
- String string = Resources.toString(url, Charsets.UTF_8);
- return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
- }
-
- private static InputStream getIncorrectJson() {
- String string = "{}"; //
- return new ByteArrayInputStream((string.getBytes(StandardCharsets.UTF_8)));
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.tasks;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Vector;
-
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.oransc.policyagent.clients.A1Client;
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.configuration.ImmutableRicConfig;
-import org.oransc.policyagent.repository.ImmutablePolicy;
-import org.oransc.policyagent.repository.ImmutablePolicyType;
-import org.oransc.policyagent.repository.Lock.LockType;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Ric.RicState;
-import org.oransc.policyagent.repository.Rics;
-import reactor.core.publisher.Mono;
-
-@ExtendWith(MockitoExtension.class)
-class RicSupervisionTest {
- private static final String POLICY_TYPE_1_NAME = "type1";
- private static final PolicyType POLICY_TYPE_1 = ImmutablePolicyType.builder() //
- .name(POLICY_TYPE_1_NAME) //
- .schema("") //
- .build();
-
- private static final Ric RIC_1 = new Ric(ImmutableRicConfig.builder() //
- .name("RIC_1") //
- .baseUrl("baseUrl1") //
- .managedElementIds(new Vector<String>(Arrays.asList("kista_1", "kista_2"))) //
- .controllerName("controllerName") //
- .build());
-
- private static final String POLICY_1_ID = "policyId1";
- private static final Policy POLICY_1 = ImmutablePolicy.builder() //
- .id(POLICY_1_ID) //
- .json("") //
- .ownerServiceName("service") //
- .ric(RIC_1) //
- .type(POLICY_TYPE_1) //
- .lastModified("now") //
- .isTransient(false) //
- .build();
-
- private static final Policy POLICY_2 = ImmutablePolicy.builder() //
- .id("policyId2") //
- .json("") //
- .ownerServiceName("service") //
- .ric(RIC_1) //
- .type(POLICY_TYPE_1) //
- .lastModified("now") //
- .isTransient(false) //
- .build();
-
- @Mock
- private A1Client a1ClientMock;
-
- @Mock
- private A1ClientFactory a1ClientFactory;
-
- @Mock
- private RicSynchronizationTask synchronizationTaskMock;
-
- private final PolicyTypes types = new PolicyTypes();
- private Policies policies = new Policies();
- private Rics rics = new Rics();
-
- @BeforeEach
- void init() {
- types.clear();
- policies.clear();
- rics.clear();
- RIC_1.setState(RicState.UNAVAILABLE);
- RIC_1.clearSupportedPolicyTypes();
- }
-
- @AfterEach
- void verifyNoRicLocks() {
- for (Ric ric : this.rics.getRics()) {
- ric.getLock().lockBlocking(LockType.EXCLUSIVE);
- ric.getLock().unlockBlocking();
- assertThat(ric.getLock().getLockCounter()).isZero();
- }
- }
-
- @Test
- void whenRicIdleAndNoChangedPoliciesOrPolicyTypes_thenNoSynchronization() {
- doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any(Ric.class));
- RIC_1.setState(RicState.AVAILABLE);
- RIC_1.addSupportedPolicyType(POLICY_TYPE_1);
- rics.put(RIC_1);
-
- types.put(POLICY_TYPE_1);
-
- policies.put(POLICY_1);
-
- setUpGetPolicyIdentitiesToReturn(new ArrayList<>(Arrays.asList(POLICY_1_ID)));
- setUpGetPolicyTypeIdentitiesToReturn(new ArrayList<>(Arrays.asList(POLICY_TYPE_1_NAME)));
-
- RicSupervision supervisorUnderTest = spy(new RicSupervision(rics, policies, a1ClientFactory, types, null));
-
- supervisorUnderTest.checkAllRics();
-
- verify(supervisorUnderTest).checkAllRics();
- verifyNoMoreInteractions(supervisorUnderTest);
- }
-
- @Test
- void whenRicUndefined_thenSynchronization() {
- doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any(Ric.class));
- RIC_1.setState(RicState.UNAVAILABLE);
- rics.put(RIC_1);
-
- RicSupervision supervisorUnderTest = spy(new RicSupervision(rics, policies, a1ClientFactory, types, null));
-
- doReturn(synchronizationTaskMock).when(supervisorUnderTest).createSynchronizationTask();
-
- supervisorUnderTest.checkAllRics();
-
- verify(supervisorUnderTest).checkAllRics();
- verify(supervisorUnderTest).createSynchronizationTask();
- verify(synchronizationTaskMock).run(RIC_1);
- verifyNoMoreInteractions(supervisorUnderTest);
- }
-
- @Test
- void whenRicSynchronizing_thenNoSynchronization() {
- doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any(Ric.class));
- RIC_1.setState(RicState.SYNCHRONIZING);
- rics.put(RIC_1);
-
- RicSupervision supervisorUnderTest = spy(new RicSupervision(rics, policies, a1ClientFactory, types, null));
-
- supervisorUnderTest.checkAllRics();
-
- verify(supervisorUnderTest).checkAllRics();
- verifyNoMoreInteractions(supervisorUnderTest);
- }
-
- @Test
- void whenRicIdleAndErrorGettingPolicyIdentities_thenNoSynchronization() {
- doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any(Ric.class));
- RIC_1.setState(RicState.AVAILABLE);
- RIC_1.addSupportedPolicyType(POLICY_TYPE_1);
- rics.put(RIC_1);
-
- setUpGetPolicyIdentitiesToReturn(new Exception("Failed"));
-
- RicSupervision supervisorUnderTest = spy(new RicSupervision(rics, policies, a1ClientFactory, types, null));
- supervisorUnderTest.checkAllRics();
-
- verify(supervisorUnderTest).checkAllRics();
- verifyNoMoreInteractions(supervisorUnderTest);
- assertThat(RIC_1.getState()).isEqualTo(RicState.UNAVAILABLE);
- }
-
- @Test
- void whenRicIdleAndNotSameAmountOfPolicies_thenSynchronization() {
- doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any(Ric.class));
- RIC_1.setState(RicState.AVAILABLE);
- rics.put(RIC_1);
-
- policies.put(POLICY_1);
- policies.put(POLICY_2);
-
- setUpGetPolicyIdentitiesToReturn(new ArrayList<>(Arrays.asList(POLICY_1_ID)));
-
- RicSupervision supervisorUnderTest = spy(new RicSupervision(rics, policies, a1ClientFactory, types, null));
-
- doReturn(synchronizationTaskMock).when(supervisorUnderTest).createSynchronizationTask();
-
- supervisorUnderTest.checkAllRics();
-
- verify(supervisorUnderTest).checkAllRics();
- verify(supervisorUnderTest).createSynchronizationTask();
- verify(synchronizationTaskMock).run(RIC_1);
- verifyNoMoreInteractions(supervisorUnderTest);
- }
-
- @Test
- void whenRicIdleAndSameAmountOfPoliciesButNotSamePolicies_thenSynchronization() {
- doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any(Ric.class));
- RIC_1.setState(RicState.AVAILABLE);
- rics.put(RIC_1);
-
- policies.put(POLICY_1);
- policies.put(POLICY_2);
-
- setUpGetPolicyIdentitiesToReturn(new ArrayList<>(Arrays.asList(POLICY_1_ID, "Another_policy")));
-
- RicSupervision supervisorUnderTest = spy(new RicSupervision(rics, policies, a1ClientFactory, types, null));
-
- doReturn(synchronizationTaskMock).when(supervisorUnderTest).createSynchronizationTask();
-
- supervisorUnderTest.checkAllRics();
-
- verify(supervisorUnderTest).checkAllRics();
- verify(supervisorUnderTest).createSynchronizationTask();
- verify(synchronizationTaskMock).run(RIC_1);
- verifyNoMoreInteractions(supervisorUnderTest);
- }
-
- @Test
- void whenRicIdleAndErrorGettingPolicyTypes_thenNoSynchronization() {
- doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any(Ric.class));
- RIC_1.setState(RicState.AVAILABLE);
- RIC_1.addSupportedPolicyType(POLICY_TYPE_1);
- rics.put(RIC_1);
-
- setUpGetPolicyIdentitiesToReturn(Collections.emptyList());
- setUpGetPolicyTypeIdentitiesToReturn(new Exception("Failed"));
-
- RicSupervision supervisorUnderTest = spy(new RicSupervision(rics, policies, a1ClientFactory, types, null));
- supervisorUnderTest.checkAllRics();
-
- verify(supervisorUnderTest).checkAllRics();
- verifyNoMoreInteractions(supervisorUnderTest);
- }
-
- @Test
- void whenRicIdleAndNotSameAmountOfPolicyTypes_thenSynchronization() {
- doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any(Ric.class));
- RIC_1.setState(RicState.AVAILABLE);
- RIC_1.addSupportedPolicyType(POLICY_TYPE_1);
- rics.put(RIC_1);
-
- types.put(POLICY_TYPE_1);
-
- setUpGetPolicyIdentitiesToReturn(Collections.emptyList());
- setUpGetPolicyTypeIdentitiesToReturn(new ArrayList<>(Arrays.asList(POLICY_TYPE_1_NAME, "another_policy_type")));
-
- RicSupervision supervisorUnderTest = spy(new RicSupervision(rics, policies, a1ClientFactory, types, null));
-
- doReturn(synchronizationTaskMock).when(supervisorUnderTest).createSynchronizationTask();
-
- supervisorUnderTest.checkAllRics();
-
- verify(supervisorUnderTest).checkAllRics();
- verify(supervisorUnderTest).createSynchronizationTask();
- verify(synchronizationTaskMock).run(RIC_1);
- verifyNoMoreInteractions(supervisorUnderTest);
- }
-
- @Test
- void whenRicIdleAndSameAmountOfPolicyTypesButNotSameTypes_thenSynchronization() {
- doReturn(Mono.just(a1ClientMock)).when(a1ClientFactory).createA1Client(any(Ric.class));
- PolicyType policyType2 = ImmutablePolicyType.builder() //
- .name("policyType2") //
- .schema("") //
- .build();
-
- RIC_1.setState(RicState.AVAILABLE);
- RIC_1.addSupportedPolicyType(POLICY_TYPE_1);
- RIC_1.addSupportedPolicyType(policyType2);
- rics.put(RIC_1);
-
- setUpGetPolicyIdentitiesToReturn(Collections.emptyList());
- setUpGetPolicyTypeIdentitiesToReturn(new ArrayList<>(Arrays.asList(POLICY_TYPE_1_NAME, "another_policy_type")));
-
- RicSupervision supervisorUnderTest = spy(new RicSupervision(rics, policies, a1ClientFactory, types, null));
-
- doReturn(synchronizationTaskMock).when(supervisorUnderTest).createSynchronizationTask();
-
- supervisorUnderTest.checkAllRics();
-
- verify(supervisorUnderTest).checkAllRics();
- verify(supervisorUnderTest).createSynchronizationTask();
- verify(synchronizationTaskMock).run(RIC_1);
- verifyNoMoreInteractions(supervisorUnderTest);
- }
-
- @SuppressWarnings("unchecked")
- private void setUpGetPolicyIdentitiesToReturn(Object returnValue) {
- if (returnValue instanceof List<?>) {
- when(a1ClientMock.getPolicyIdentities()).thenReturn(Mono.just((List<String>) returnValue));
- } else if (returnValue instanceof Exception) {
- when(a1ClientMock.getPolicyIdentities()).thenReturn(Mono.error((Exception) returnValue));
- }
- }
-
- @SuppressWarnings("unchecked")
- private void setUpGetPolicyTypeIdentitiesToReturn(Object returnValue) {
- if (returnValue instanceof List<?>) {
- when(a1ClientMock.getPolicyTypeIdentities()).thenReturn(Mono.just((List<String>) returnValue));
- } else if (returnValue instanceof Exception) {
- when(a1ClientMock.getPolicyTypeIdentities()).thenReturn(Mono.error((Exception) returnValue));
- }
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.tasks;
-
-import static ch.qos.logback.classic.Level.WARN;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.read.ListAppender;
-
-import java.time.Duration;
-import java.util.Arrays;
-import java.util.Collections;
-
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.oransc.policyagent.clients.A1Client;
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.clients.AsyncRestClient;
-import org.oransc.policyagent.configuration.ImmutableRicConfig;
-import org.oransc.policyagent.repository.ImmutablePolicy;
-import org.oransc.policyagent.repository.ImmutablePolicyType;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Ric.RicState;
-import org.oransc.policyagent.repository.Service;
-import org.oransc.policyagent.repository.Services;
-import org.oransc.policyagent.utils.LoggingUtils;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-
-@ExtendWith(MockitoExtension.class)
-class RicSynchronizationTaskTest {
- private static final String POLICY_TYPE_1_NAME = "type1";
- private static final PolicyType POLICY_TYPE_1 = ImmutablePolicyType.builder() //
- .name(POLICY_TYPE_1_NAME) //
- .schema("") //
- .build();
-
- private static final String RIC_1_NAME = "ric1";
- private static final Ric RIC_1 = new Ric(ImmutableRicConfig.builder() //
- .name(RIC_1_NAME) //
- .baseUrl("baseUrl1") //
- .managedElementIds(Collections.emptyList()) //
- .controllerName("controllerName") //
- .build());
-
- private static Policy createPolicy(String policyId, boolean isTransient) {
- return ImmutablePolicy.builder() //
- .id(policyId) //
- .json("") //
- .ownerServiceName("service") //
- .ric(RIC_1) //
- .type(POLICY_TYPE_1) //
- .lastModified("now") //
- .isTransient(isTransient) //
- .build();
- }
-
- private static final Policy POLICY_1 = createPolicy("policyId1", false);
-
- private static final String SERVICE_1_NAME = "service1";
- private static final String SERVICE_1_CALLBACK_URL = "callbackUrl";
- private static final Service SERVICE_1 = new Service(SERVICE_1_NAME, Duration.ofSeconds(1), SERVICE_1_CALLBACK_URL);
-
- @Mock
- private A1Client a1ClientMock;
-
- @Mock
- private A1ClientFactory a1ClientFactoryMock;
-
- private PolicyTypes policyTypes;
- private Policies policies;
- private Services services;
-
- @BeforeEach
- void init() {
- policyTypes = new PolicyTypes();
- policies = new Policies();
- services = new Services();
- RIC_1.setState(RicState.UNAVAILABLE);
- RIC_1.clearSupportedPolicyTypes();
- }
-
- @Test
- void ricAlreadySynchronizing_thenNoSynchronization() {
- RIC_1.setState(RicState.SYNCHRONIZING);
- RIC_1.addSupportedPolicyType(POLICY_TYPE_1);
-
- policyTypes.put(POLICY_TYPE_1);
- policies.put(POLICY_1);
-
- RicSynchronizationTask synchronizerUnderTest =
- new RicSynchronizationTask(a1ClientFactoryMock, policyTypes, policies, services);
-
- synchronizerUnderTest.run(RIC_1);
-
- verifyNoInteractions(a1ClientMock);
-
- assertThat(policyTypes.size()).isEqualTo(1);
- assertThat(policies.size()).isEqualTo(1);
- assertThat(RIC_1.getState()).isEqualTo(RicState.SYNCHRONIZING);
- assertThat(RIC_1.getSupportedPolicyTypeNames()).hasSize(1);
- }
-
- @Test
- void ricIdlePolicyTypeInRepo_thenSynchronizationWithReuseOfTypeFromRepoAndCorrectServiceNotified() {
- RIC_1.setState(RicState.AVAILABLE);
-
- policyTypes.put(POLICY_TYPE_1);
-
- services.put(SERVICE_1);
- Service serviceWithoutCallbackUrlShouldNotBeNotified = new Service("service2", Duration.ofSeconds(1), "");
- services.put(serviceWithoutCallbackUrlShouldNotBeNotified);
-
- setUpCreationOfA1Client();
- simulateRicWithOnePolicyType();
-
- RicSynchronizationTask synchronizerUnderTest =
- spy(new RicSynchronizationTask(a1ClientFactoryMock, policyTypes, policies, services));
-
- AsyncRestClient restClientMock = setUpCreationOfAsyncRestClient(synchronizerUnderTest);
- when(restClientMock.put(anyString(), anyString())).thenReturn(Mono.just("Ok"));
-
- synchronizerUnderTest.run(RIC_1);
-
- verify(a1ClientMock, times(1)).getPolicyTypeIdentities();
- verifyNoMoreInteractions(a1ClientMock);
-
- verify(synchronizerUnderTest).run(RIC_1);
- verify(synchronizerUnderTest).createNotificationClient(SERVICE_1_CALLBACK_URL);
- verifyNoMoreInteractions(synchronizerUnderTest);
-
- verify(restClientMock).put("", "Synchronization completed for:" + RIC_1_NAME);
- verifyNoMoreInteractions(restClientMock);
-
- assertThat(policyTypes.size()).isEqualTo(1);
- assertThat(policies.size()).isZero();
- assertThat(RIC_1.getState()).isEqualTo(RicState.AVAILABLE);
- }
-
- @Test
- void ricIdlePolicyTypeNotInRepo_thenSynchronizationWithTypeFromRic() throws Exception {
- RIC_1.setState(RicState.AVAILABLE);
-
- setUpCreationOfA1Client();
- simulateRicWithOnePolicyType();
- String typeSchema = "schema";
- when(a1ClientMock.getPolicyTypeSchema(POLICY_TYPE_1_NAME)).thenReturn(Mono.just(typeSchema));
-
- RicSynchronizationTask synchronizerUnderTest =
- new RicSynchronizationTask(a1ClientFactoryMock, policyTypes, policies, services);
-
- synchronizerUnderTest.run(RIC_1);
-
- verify(a1ClientMock).getPolicyTypeIdentities();
- verifyNoMoreInteractions(a1ClientMock);
-
- assertThat(policyTypes.size()).isEqualTo(1);
- assertThat(policyTypes.getType(POLICY_TYPE_1_NAME).schema()).isEqualTo(typeSchema);
- assertThat(policies.size()).isZero();
- assertThat(RIC_1.getState()).isEqualTo(RicState.AVAILABLE);
- }
-
- @Test
- void ricIdleAndHavePolicies_thenSynchronizationWithRecreationOfPolicies() {
- RIC_1.setState(RicState.AVAILABLE);
-
- Policy transientPolicy = createPolicy("transientPolicyId", true);
-
- policies.put(transientPolicy);
- policies.put(POLICY_1);
-
- setUpCreationOfA1Client();
- simulateRicWithNoPolicyTypes();
-
- when(a1ClientMock.deleteAllPolicies()).thenReturn(Flux.just("OK"));
- when(a1ClientMock.putPolicy(any(Policy.class))).thenReturn(Mono.just("OK"));
-
- RicSynchronizationTask synchronizerUnderTest =
- new RicSynchronizationTask(a1ClientFactoryMock, policyTypes, policies, services);
-
- synchronizerUnderTest.run(RIC_1);
-
- verify(a1ClientMock).deleteAllPolicies();
- verify(a1ClientMock).putPolicy(POLICY_1);
- verifyNoMoreInteractions(a1ClientMock);
-
- assertThat(policyTypes.size()).isZero();
- assertThat(policies.size()).isEqualTo(1); // The transient policy shall be deleted
- assertThat(RIC_1.getState()).isEqualTo(RicState.AVAILABLE);
- }
-
- @Test
- void ricIdleAndErrorDeletingPoliciesFirstTime_thenSynchronizationWithDeletionOfPolicies() {
- RIC_1.setState(RicState.AVAILABLE);
-
- policies.put(POLICY_1);
-
- setUpCreationOfA1Client();
- simulateRicWithNoPolicyTypes();
-
- when(a1ClientMock.deleteAllPolicies()) //
- .thenReturn(Flux.error(new Exception("Exception"))) //
- .thenReturn(Flux.just("OK"));
-
- RicSynchronizationTask synchronizerUnderTest =
- new RicSynchronizationTask(a1ClientFactoryMock, policyTypes, policies, services);
-
- synchronizerUnderTest.run(RIC_1);
-
- verify(a1ClientMock, times(2)).deleteAllPolicies();
- verifyNoMoreInteractions(a1ClientMock);
-
- assertThat(policyTypes.size()).isZero();
- assertThat(policies.size()).isZero();
- assertThat(RIC_1.getState()).isEqualTo(RicState.AVAILABLE);
- }
-
- @Test
- void ricIdleAndErrorDeletingPoliciesAllTheTime_thenSynchronizationWithFailedRecovery() {
- RIC_1.setState(RicState.AVAILABLE);
-
- policies.put(POLICY_1);
-
- setUpCreationOfA1Client();
- simulateRicWithNoPolicyTypes();
-
- String originalErrorMessage = "Exception";
- when(a1ClientMock.deleteAllPolicies()).thenReturn(Flux.error(new Exception(originalErrorMessage)));
-
- RicSynchronizationTask synchronizerUnderTest =
- new RicSynchronizationTask(a1ClientFactoryMock, policyTypes, policies, services);
-
- final ListAppender<ILoggingEvent> logAppender =
- LoggingUtils.getLogListAppender(RicSynchronizationTask.class, WARN);
-
- synchronizerUnderTest.run(RIC_1);
-
- verifyCorrectLogMessage(0, logAppender,
- "Synchronization failure for ric: " + RIC_1_NAME + ", reason: " + originalErrorMessage);
-
- verify(a1ClientMock, times(2)).deleteAllPolicies();
- verifyNoMoreInteractions(a1ClientMock);
-
- assertThat(policyTypes.size()).isZero();
- assertThat(policies.size()).isZero();
- assertThat(RIC_1.getState()).isEqualTo(RicState.UNAVAILABLE);
- }
-
- @Test
- void ricIdlePolicyTypeInRepo_thenSynchronizationWithErrorOnServiceNotificationErrorLogged() {
- RIC_1.setState(RicState.AVAILABLE);
-
- policyTypes.put(POLICY_TYPE_1);
-
- services.put(SERVICE_1);
-
- setUpCreationOfA1Client();
- simulateRicWithOnePolicyType();
-
- final ListAppender<ILoggingEvent> logAppender =
- LoggingUtils.getLogListAppender(RicSynchronizationTask.class, WARN);
-
- RicSynchronizationTask synchronizerUnderTest =
- spy(new RicSynchronizationTask(a1ClientFactoryMock, policyTypes, policies, services));
-
- AsyncRestClient restClientMock = setUpCreationOfAsyncRestClient(synchronizerUnderTest);
- String originalErrorMessage = "Exception";
- when(restClientMock.put(anyString(), anyString())).thenReturn(Mono.error(new Exception(originalErrorMessage)));
-
- synchronizerUnderTest.run(RIC_1);
-
- ILoggingEvent loggingEvent = logAppender.list.get(0);
- assertThat(loggingEvent.getLevel()).isEqualTo(WARN);
- verifyCorrectLogMessage(0, logAppender,
- "Service notification failed for service: " + SERVICE_1_NAME + ". Cause: " + originalErrorMessage);
- }
-
- private void setUpCreationOfA1Client() {
- when(a1ClientFactoryMock.createA1Client(any(Ric.class))).thenReturn(Mono.just(a1ClientMock));
- doReturn(Flux.empty()).when(a1ClientMock).deleteAllPolicies();
- }
-
- private AsyncRestClient setUpCreationOfAsyncRestClient(RicSynchronizationTask synchronizerUnderTest) {
- AsyncRestClient restClientMock = mock(AsyncRestClient.class);
- doReturn(restClientMock).when(synchronizerUnderTest).createNotificationClient(anyString());
- return restClientMock;
- }
-
- private void simulateRicWithOnePolicyType() {
- when(a1ClientMock.getPolicyTypeIdentities()).thenReturn(Mono.just(Arrays.asList(POLICY_TYPE_1_NAME)));
- }
-
- private void simulateRicWithNoPolicyTypes() {
- when(a1ClientMock.getPolicyTypeIdentities()).thenReturn(Mono.just(Collections.emptyList()));
- }
-
- private void verifyCorrectLogMessage(int messageIndex, ListAppender<ILoggingEvent> logAppender,
- String expectedMessage) {
- ILoggingEvent loggingEvent = logAppender.list.get(messageIndex);
- assertThat(loggingEvent.getFormattedMessage()).isEqualTo(expectedMessage);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.tasks;
-
-import static ch.qos.logback.classic.Level.WARN;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.awaitility.Awaitility.await;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoInteractions;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.read.ListAppender;
-
-import java.time.Duration;
-import java.util.Collections;
-
-import org.awaitility.Durations;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mock;
-import org.mockito.junit.jupiter.MockitoExtension;
-import org.oransc.policyagent.clients.A1Client;
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.configuration.ImmutableRicConfig;
-import org.oransc.policyagent.configuration.RicConfig;
-import org.oransc.policyagent.repository.ImmutablePolicy;
-import org.oransc.policyagent.repository.ImmutablePolicyType;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.repository.Ric;
-import org.oransc.policyagent.repository.Service;
-import org.oransc.policyagent.repository.Services;
-import org.oransc.policyagent.utils.LoggingUtils;
-import reactor.core.publisher.Mono;
-
-@ExtendWith(MockitoExtension.class)
-class ServiceSupervisionTest {
-
- private static final String SERVICE_NAME = "Service name";
- private static final String RIC_NAME = "name";
- private static final String POLICY_ID = "policy";
-
- @Mock
- A1ClientFactory a1ClientFactoryMock;
- @Mock
- A1Client a1ClientMock;
-
- private Services services;
- private Service service;
- private Policies policies;
- private RicConfig ricConfig = ImmutableRicConfig.builder() //
- .name(RIC_NAME) //
- .baseUrl("baseUrl") //
- .managedElementIds(Collections.emptyList()) //
- .controllerName("") //
- .build();
- private Ric ric = new Ric(ricConfig);
- private PolicyType policyType = ImmutablePolicyType.builder() //
- .name("plicyTypeName") //
- .schema("schema") //
- .build();
- private Policy policy = ImmutablePolicy.builder() //
- .id(POLICY_ID) //
- .json("json") //
- .ownerServiceName(SERVICE_NAME) //
- .ric(ric) //
- .type(policyType) //
- .lastModified("lastModified") //
- .isTransient(false) //
- .build();
-
- @Test
- void serviceExpired_policyAndServiceAreDeletedInRepoAndPolicyIsDeletedInRic() {
- setUpRepositoryWithKeepAliveInterval(Duration.ofSeconds(2));
-
- setUpCreationOfA1Client();
- when(a1ClientMock.deletePolicy(any(Policy.class))).thenReturn(Mono.just("Policy deleted"));
-
- ServiceSupervision serviceSupervisionUnderTest =
- new ServiceSupervision(services, policies, a1ClientFactoryMock);
-
- await().atMost(Durations.FIVE_SECONDS).with().pollInterval(Durations.ONE_SECOND).until(service::isExpired);
-
- serviceSupervisionUnderTest.checkAllServices().blockLast();
-
- assertThat(policies.size()).isZero();
- assertThat(services.size()).isZero();
-
- verify(a1ClientMock).deletePolicy(policy);
- verifyNoMoreInteractions(a1ClientMock);
- }
-
- @Test
- void serviceExpiredButDeleteInRicFails_policyAndServiceAreDeletedInRepoAndErrorLoggedForRic() {
- setUpRepositoryWithKeepAliveInterval(Duration.ofSeconds(2));
-
- setUpCreationOfA1Client();
- String originalErrorMessage = "Failed";
- when(a1ClientMock.deletePolicy(any(Policy.class))).thenReturn(Mono.error(new Exception(originalErrorMessage)));
-
- ServiceSupervision serviceSupervisionUnderTest =
- new ServiceSupervision(services, policies, a1ClientFactoryMock);
-
- await().atMost(Durations.FIVE_SECONDS).with().pollInterval(Durations.ONE_SECOND).until(service::isExpired);
-
- final ListAppender<ILoggingEvent> logAppender = LoggingUtils.getLogListAppender(ServiceSupervision.class, WARN);
-
- serviceSupervisionUnderTest.checkAllServices().blockLast();
-
- assertThat(policies.size()).isZero();
- assertThat(services.size()).isZero();
-
- ILoggingEvent loggingEvent = logAppender.list.get(0);
- assertThat(loggingEvent.getLevel()).isEqualTo(WARN);
- String expectedLogMessage =
- "Could not delete policy: " + POLICY_ID + " from ric: " + RIC_NAME + ". Cause: " + originalErrorMessage;
- assertThat(loggingEvent.getFormattedMessage()).isEqualTo(expectedLogMessage);
- }
-
- @Test
- void serviceNotExpired_shouldNotBeChecked() {
- setUpRepositoryWithKeepAliveInterval(Duration.ofSeconds(2));
-
- ServiceSupervision serviceSupervisionUnderTest =
- new ServiceSupervision(services, policies, a1ClientFactoryMock);
-
- serviceSupervisionUnderTest.checkAllServices().blockLast();
-
- assertThat(policies.size()).isEqualTo(1);
- assertThat(services.size()).isEqualTo(1);
-
- verifyNoInteractions(a1ClientFactoryMock);
- verifyNoInteractions(a1ClientMock);
- }
-
- @Test
- void serviceWithoutKeepAliveInterval_shouldNotBeChecked() {
- setUpRepositoryWithKeepAliveInterval(Duration.ofSeconds(0));
-
- ServiceSupervision serviceSupervisionUnderTest =
- new ServiceSupervision(services, policies, a1ClientFactoryMock);
-
- serviceSupervisionUnderTest.checkAllServices().blockLast();
-
- assertThat(policies.size()).isEqualTo(1);
- assertThat(services.size()).isEqualTo(1);
-
- verifyNoInteractions(a1ClientFactoryMock);
- verifyNoInteractions(a1ClientMock);
- }
-
- private void setUpCreationOfA1Client() {
- when(a1ClientFactoryMock.createA1Client(any(Ric.class))).thenReturn(Mono.just(a1ClientMock));
- }
-
- private void setUpRepositoryWithKeepAliveInterval(Duration keepAliveInterval) {
- services = new Services();
- service = new Service(SERVICE_NAME, keepAliveInterval, "callbackUrl");
- services.put(service);
-
- policies = new Policies();
- policies.put(policy);
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.utils;
-
-import ch.qos.logback.classic.Level;
-import ch.qos.logback.classic.Logger;
-import ch.qos.logback.classic.spi.ILoggingEvent;
-import ch.qos.logback.core.read.ListAppender;
-
-import org.slf4j.LoggerFactory;
-
-public class LoggingUtils {
-
- /**
- * Returns a ListAppender that contains all logging events. Call this method right before calling the tested
- * method.
- *
- * @return the log list appender for the given class.
- */
- public static ListAppender<ILoggingEvent> getLogListAppender(Class<?> logClass) {
- return getLogListAppender(logClass, Level.ALL);
- }
-
- /**
- * Returns a ListAppender that contains events for the given level. Call this method right before calling the tested
- * method.
- *
- * @param logClass class whose appender is wanted.
- * @param level the log level to log at.
- *
- * @return the log list appender for the given class logging on the given level.
- */
- public static ListAppender<ILoggingEvent> getLogListAppender(Class<?> logClass, Level level) {
- Logger logger = (Logger) LoggerFactory.getLogger(logClass);
- logger.setLevel(level);
- ListAppender<ILoggingEvent> listAppender = new ListAppender<>();
- listAppender.start();
- logger.addAppender(listAppender);
-
- return listAppender;
- }
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2020 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.utils;
-
-import java.nio.charset.StandardCharsets;
-import java.time.Duration;
-import java.util.List;
-import java.util.Vector;
-
-import org.oransc.policyagent.clients.A1Client;
-import org.oransc.policyagent.repository.Policies;
-import org.oransc.policyagent.repository.Policy;
-import org.oransc.policyagent.repository.PolicyType;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.springframework.http.HttpStatus;
-import org.springframework.web.reactive.function.client.WebClientResponseException;
-
-import reactor.core.publisher.Flux;
-import reactor.core.publisher.Mono;
-import reactor.core.publisher.MonoSink;
-
-public class MockA1Client implements A1Client {
- Policies policies = new Policies();
- private final PolicyTypes policyTypes;
- private final Duration asynchDelay;
-
- public MockA1Client(PolicyTypes policyTypes, Duration asynchDelay) {
- this.policyTypes = policyTypes;
- this.asynchDelay = asynchDelay;
- }
-
- @Override
- public Mono<List<String>> getPolicyTypeIdentities() {
- List<String> result = new Vector<>();
- for (PolicyType p : this.policyTypes.getAll()) {
- result.add(p.name());
- }
- return mono(result);
- }
-
- @Override
- public Mono<List<String>> getPolicyIdentities() {
- Vector<String> result = new Vector<>();
- for (Policy policy : policies.getAll()) {
- result.add(policy.id());
- }
-
- return mono(result);
- }
-
- @Override
- public Mono<String> getPolicyTypeSchema(String policyTypeId) {
- try {
- return mono(this.policyTypes.getType(policyTypeId).schema());
- } catch (Exception e) {
- return Mono.error(e);
- }
- }
-
- @Override
- public Mono<String> putPolicy(Policy p) {
- this.policies.put(p);
- return mono("OK");
-
- }
-
- @Override
- public Mono<String> deletePolicy(Policy policy) {
- this.policies.remove(policy);
- return mono("OK");
- }
-
- public Policies getPolicies() {
- return this.policies;
- }
-
- @Override
- public Mono<A1ProtocolType> getProtocolVersion() {
- return mono(A1ProtocolType.STD_V1_1);
- }
-
- @Override
- public Flux<String> deleteAllPolicies() {
- this.policies.clear();
- return mono("OK") //
- .flatMapMany(Flux::just);
- }
-
- @Override
- public Mono<String> getPolicyStatus(Policy policy) {
- return mono("OK");
- }
-
- private <T> Mono<T> mono(T value) {
- if (this.asynchDelay.isZero()) {
- return Mono.just(value);
- } else {
- return Mono.create(monoSink -> asynchResponse(monoSink, value));
- }
- }
-
- Mono<String> monoError(String responseBody, HttpStatus status) {
- byte[] responseBodyBytes = responseBody.getBytes(StandardCharsets.UTF_8);
- WebClientResponseException a1Exception = new WebClientResponseException(status.value(),
- status.getReasonPhrase(), null, responseBodyBytes, StandardCharsets.UTF_8, null);
- return Mono.error(a1Exception);
- }
-
- @SuppressWarnings("squid:S2925") // "Thread.sleep" should not be used in tests.
- private void sleep() {
- try {
- Thread.sleep(this.asynchDelay.toMillis());
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- }
-
- private <T> void asynchResponse(MonoSink<T> callback, T str) {
- Thread thread = new Thread(() -> {
- sleep(); // Simulate a network delay
- callback.success(str);
- });
- thread.start();
- }
-
-}
+++ /dev/null
-/*-
- * ========================LICENSE_START=================================
- * O-RAN-SC
- * %%
- * Copyright (C) 2019 Nordix Foundation
- * %%
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- * ========================LICENSE_END===================================
- */
-
-package org.oransc.policyagent.utils;
-
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-
-import java.lang.invoke.MethodHandles;
-import java.time.Duration;
-import java.util.HashMap;
-import java.util.Map;
-
-import org.oransc.policyagent.clients.A1Client;
-import org.oransc.policyagent.clients.A1ClientFactory;
-import org.oransc.policyagent.configuration.ApplicationConfig;
-import org.oransc.policyagent.repository.PolicyTypes;
-import org.oransc.policyagent.repository.Ric;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import reactor.core.publisher.Mono;
-
-public class MockA1ClientFactory extends A1ClientFactory {
- private static final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
- private final Map<String, MockA1Client> clients = new HashMap<>();
- private PolicyTypes policyTypes;
- private Duration asynchDelay = Duration.ofSeconds(0);
-
- public MockA1ClientFactory(PolicyTypes policyTypes) {
- super(mock(ApplicationConfig.class));
- this.policyTypes = policyTypes;
- }
-
- @Override
- public Mono<A1Client> createA1Client(Ric ric) {
- return Mono.just(getOrCreateA1Client(ric.name()));
- }
-
- public MockA1Client getOrCreateA1Client(String ricName) {
- if (!clients.containsKey(ricName)) {
- logger.debug("Creating client for RIC: {}", ricName);
- MockA1Client client = spy(new MockA1Client(policyTypes, asynchDelay));
- clients.put(ricName, client);
- }
- return clients.get(ricName);
- }
-
- public void setPolicyTypes(PolicyTypes policyTypes) {
- this.policyTypes = policyTypes;
- }
-
- /**
- * Simulate network latency. The REST responses will be generated by separate
- * threads
- *
- * @param delay the delay between the request and the response
- */
- public void setResponseDelay(Duration delay) {
- this.asynchDelay = delay;
- }
-
- public void reset() {
- this.asynchDelay = Duration.ofSeconds(0);
- clients.clear();
- }
-
- public PolicyTypes getPolicyTypes() {
- return this.policyTypes;
- }
-
-}
+++ /dev/null
-{
- "$schema": "http://json-schema.org/draft-07/schema#",
- "title": "STD_PolicyModelUnconstrained_0.2.0",
- "description": "Standard model of a policy with unconstrained scope id combinations",
- "type": "object",
- "properties": {
- "scope": {
- "type": "object",
- "properties": {
- "ueId": {"type": "string"},
- "groupId": {"type": "string"},
- "sliceId": {"type": "string"},
- "qosId": {"type": "string"},
- "cellId": {"type": "string"}
- },
- "minProperties": 1,
- "additionalProperties": false
- },
- "qosObjectives": {
- "type": "object",
- "properties": {
- "gfbr": {"type": "number"},
- "mfbr": {"type": "number"},
- "priorityLevel": {"type": "number"},
- "pdb": {"type": "number"}
- },
- "additionalProperties": false
- },
- "qoeObjectives": {
- "type": "object",
- "properties": {
- "qoeScore": {"type": "number"},
- "initialBuffering": {"type": "number"},
- "reBuffFreq": {"type": "number"},
- "stallRatio": {"type": "number"}
- },
- "additionalProperties": false
- },
- "resources": {
- "type": "array",
- "items": {
- "type": "object",
- "properties": {
- "cellIdList": {
- "type": "array",
- "minItems": 1,
- "uniqueItems": true,
- "items": {
- "type": "string"
- }
- },
- "preference": {
- "type": "string",
- "enum": [
- "SHALL",
- "PREFER",
- "AVOID",
- "FORBID"
- ]
- },
- "primary": {"type": "boolean"}
- },
- "additionalProperties": false,
- "required": ["cellIdList", "preference"]
- }
- }
- },
- "minProperties": 2,
- "additionalProperties": false,
- "required": ["scope"]
-}
+++ /dev/null
-{
- "$schema": "http://json-schema.org/draft-07/schema#",
- "title": "Example_QoETarget_1.0.0",
- "description": "Example QoE Target policy type",
- "type": "object",
- "properties": {
- "scope": {
- "type": "object",
- "properties": {
- "ueId": {
- "type": "string"
- },
- "sliceId": {
- "type": "string"
- },
- "qosId": {
- "type": "string"
- },
- "cellId": {
- "type": "string"
- }
- },
- "additionalProperties": false,
- "required": [
- "ueId",
- "sliceId"
- ]
- },
- "statement": {
- "type": "object",
- "properties": {
- "qoeScore": {
- "type": "number"
- },
- "initialBuffering": {
- "type": "number"
- },
- "reBuffFreq": {
- "type": "number"
- },
- "stallRatio": {
- "type": "number"
- }
- },
- "minProperties": 1,
- "additionalProperties": false
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-{
- "$schema": "http://json-schema.org/draft-07/schema#",
- "title": "ERIC_QoSNudging_0.2.0",
- "description": "QoS nudging policy type with priorityLevel and ueId and qosId as scope",
- "type": "object",
- "properties": {
- "scope": {
- "type": "object",
- "properties": {
- "ueId": {"type": "string"},
- "qosId": {"type": "string"}
- },
- "additionalProperties": false,
- "required": ["ueId", "qosId"]
- },
- "qosObjectives": {
- "type": "object",
- "properties": {
- "priorityLevel": {"type": "number"}
- },
- "additionalProperties": false,
- "required": ["priorityLevel"]
- }
- },
- "additionalProperties": false,
- "required": ["scope", "qosObjectives"]
-}
+++ /dev/null
-{
- "config": {
- "//description": "Application configuration",
- "ric": [
- {
- "name": "ric1",
- "baseUrl": "http://localhost:8080/",
- "managedElementIds": [
- "kista_1",
- "kista_2"
- ]
- },
- {
- "name": "ric2",
- "baseUrl": "http://localhost:8081/",
- "managedElementIds": [
- "kista_3",
- "kista_4"
- ]
- }
- ],
- "streams_publishes": {
- "dmaap_publisher": {
- "type": "message_router",
- "dmaap_info": {
- "topic_url": "http://admin:admin@localhost:6845/events/A1-POLICY-AGENT-WRITE"
- }
- }
- },
- "streams_subscribes": {
- "dmaap_subscriber": {
- "type": "message_router",
- "dmaap_info": {
- "topic_url": "http://admin:admin@localhost:6845/events/A1-POLICY-AGENT-READ/users/policy-agent?timeout=15000&limit=100"
- }
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-{
- "config": {
- "controller": [
- {
- "name": "controller1",
- "baseUrl": "http://localhost:8083/",
- "userName": "user",
- "password": "password"
- }
- ],
- "ric": [
- {
- "name": "ric1",
- "controller": "controller1",
- "baseUrl": "http://localhost:8083/",
- "managedElementIds": [
- "kista_1",
- "kista_2"
- ]
- },
- {
- "name": "ric2",
- "baseUrl": "http://localhost:8085/",
- "managedElementIds": [
- "kista_3",
- "kista_4"
- ]
- }
- ],
- "streams_publishes": {
- "dmaap_publisher": {
- "type": "message_router",
- "dmaap_info": {
- "topic_url": "http://admin:admin@localhost:6845/events/A1-POLICY-AGENT-WRITE"
- }
- }
- },
- "streams_subscribes": {
- "dmaap_subscriber": {
- "type": "message_router",
- "dmaap_info": {
- "topic_url": "http://admin:admin@localhost:6845/events/A1-POLICY-AGENT-READ/users/policy-agent?timeout=15000&limit=100"
- }
- }
- }
- }
-}
\ No newline at end of file
+++ /dev/null
-{
- "name": "pt1",
- "description": "pt1 policy type",
- "policy_type_id": 1,
- "create_schema": {
- "$schema": "http://json-schema.org/draft-07/schema#",
- "title": "OSC_Type1_1.0.0",
- "description": "Type 1 policy type",
- "type": "object",
- "properties": {
- "scope": {
- "type": "object",
- "properties": {
- "ueId": {
- "type": "string"
- },
- "qosId": {
- "type": "string"
- }
- },
- "additionalProperties": false,
- "required": [
- "ueId",
- "qosId"
- ]
- },
- "qosObjective": {
- "type": "object",
- "properties": {
- "priorityLevel": {
- "type": "number"
- }
- },
- "additionalProperties": false,
- "required": [
- "priorityLevel"
- ]
- }
- },
- "additionalProperties": false,
- "required": [
- "scope", "qosObjective"
- ]
- }
-}
</properties>
<modules>
<module>policy-agent</module>
- <module>sdnc-a1-controller</module>
<module>enrichment-coordinator-service</module>
<module>r-app-catalogue</module>
</modules>