swagger: '2.0'
info:
- description: This page lists all the rest apis for Policy server.
+ description: This page lists all the rest apis for the service.
version: '1.0'
- title: Policy server
+ title: A1 Policy management service
host: 'localhost:8081'
basePath: /
tags:
- - name: operation-handler
- description: Operation Handler
- - name: policy-controller
+ - name: A1 Policy Management
description: Policy Controller
- - name: ric-repository-controller
+ - name: Health check
+ description: Status Controller
+ - name: RIC Repository
description: Ric Repository Controller
- - name: service-controller
+ - name: Service registry and supervision
description: Service Controller
- - name: status-controller
- description: Status Controller
+ - name: operation-handler
+ description: Operation Handler
- name: web-mvc-links-handler
description: Web Mvc Links Handler
paths:
/policies:
get:
tags:
- - policy-controller
+ - A1 Policy Management
summary: Query policies
operationId: getPoliciesUsingGET
produces:
'403':
description: Forbidden
'404':
- description: Not Found
+ description: RIC or type not found
+ schema:
+ type: string
deprecated: false
/policy:
get:
tags:
- - policy-controller
+ - A1 Policy Management
summary: Returns a policy configuration
operationId: getPolicyUsingGET
produces:
description: Policy found
schema:
type: object
- '204':
- description: Policy is not found
- schema:
- type: string
'401':
description: Unauthorized
'403':
description: Forbidden
'404':
- description: Not Found
+ description: Policy is not found
deprecated: false
put:
tags:
- - policy-controller
+ - A1 Policy Management
summary: Put a policy
operationId: putPolicyUsingPUT
consumes:
type: string
responses:
'200':
- description: Policy created or updated
+ description: Policy updated
schema:
type: string
'201':
- description: Created
+ description: Policy created
+ schema:
+ type: string
'401':
description: Unauthorized
'403':
description: Forbidden
'404':
- description: Not Found
+ description: RIC or policy type is not found
+ schema:
+ type: string
+ '405':
+ description: Change is not allowed
+ schema:
+ type: string
+ '423':
+ description: RIC is locked
+ schema:
+ type: string
deprecated: false
delete:
tags:
- - policy-controller
+ - A1 Policy Management
summary: Delete a policy
operationId: deletePolicyUsingDELETE
produces:
description: Unauthorized
'403':
description: Forbidden
+ '404':
+ description: Policy is not found
+ schema:
+ type: string
+ '423':
+ description: RIC is locked
+ schema:
+ type: string
deprecated: false
/policy_schema:
get:
tags:
- - policy-controller
+ - A1 Policy Management
summary: Returns one policy type schema definition
operationId: getPolicySchemaUsingGET
produces:
'403':
description: Forbidden
'404':
- description: Not Found
+ description: RIC is not found
+ schema:
+ type: string
deprecated: false
/policy_schemas:
get:
tags:
- - policy-controller
+ - A1 Policy Management
summary: Returns policy type schema definitions
operationId: getPolicySchemasUsingGET
produces:
'403':
description: Forbidden
'404':
- description: Not Found
+ description: RIC is not found
+ schema:
+ type: string
deprecated: false
/policy_status:
get:
tags:
- - policy-controller
+ - A1 Policy Management
summary: Returns a policy status
operationId: getPolicyStatusUsingGET
produces:
description: Policy status
schema:
type: object
- '204':
- description: Policy is not found
- schema:
- type: string
'401':
description: Unauthorized
'403':
description: Forbidden
'404':
- description: Not Found
+ description: Policy is not found
+ schema:
+ type: string
deprecated: false
/policy_types:
get:
tags:
- - policy-controller
+ - A1 Policy Management
summary: Query policy type names
operationId: getPolicyTypesUsingGET
produces:
'403':
description: Forbidden
'404':
- description: Not Found
+ description: RIC is not found
+ schema:
+ type: string
deprecated: false
/ric:
get:
tags:
- - ric-repository-controller
+ - RIC Repository
summary: Returns the name of a RIC managing one Mananged Element
operationId: getRicUsingGET
produces:
/rics:
get:
tags:
- - ric-repository-controller
+ - RIC Repository
summary: Query NearRT RIC information
operationId: getRicsUsingGET
produces:
'403':
description: Forbidden
'404':
- description: Not Found
+ description: Policy type is not found
+ schema:
+ type: string
deprecated: false
/service:
put:
tags:
- - service-controller
+ - Service registry and supervision
summary: Register a service
operationId: putServiceUsingPUT
consumes:
type: string
'201':
description: Created
+ '400':
+ description: Cannot parse the ServiceRegistrationInfo
+ schema:
+ type: string
'401':
description: Unauthorized
'403':
/services:
get:
tags:
- - service-controller
+ - Service registry and supervision
summary: Returns service information
operationId: getServicesUsingGET
produces:
'403':
description: Forbidden
'404':
- description: Not Found
+ description: Service is not found
+ schema:
+ type: string
deprecated: false
delete:
tags:
- - service-controller
+ - Service registry and supervision
summary: Delete a service
operationId: deleteServiceUsingDELETE
produces:
- '*/*'
parameters:
- - name: serviceName
+ - name: name
in: query
- description: serviceName
+ description: name
required: true
type: string
responses:
schema:
type: string
'204':
- description: No Content
+ description: OK
+ schema:
+ type: string
'401':
description: Unauthorized
'403':
description: Forbidden
+ '404':
+ description: Service not found
+ schema:
+ type: string
deprecated: false
/services/keepalive:
post:
tags:
- - service-controller
- summary: Keep the poilicies alive for a service
+ - Service registry and supervision
+ summary: Keep the policies alive for a service
operationId: keepAliveServiceUsingPOST
consumes:
- application/json
produces:
- '*/*'
parameters:
- - name: serviceName
+ - name: name
in: query
- description: serviceName
+ description: name
required: true
type: string
responses:
/status:
get:
tags:
- - status-controller
+ - Health check
summary: Returns status and statistics of this service
operationId: getStatusUsingGET
produces:
title: 'Map«string,Link»'
additionalProperties:
$ref: '#/definitions/Link'
- Mono«ResponseEntity«Void»»:
+ Mono«ResponseEntity«object»»:
type: object
- title: Mono«ResponseEntity«Void»»
+ title: Mono«ResponseEntity«object»»
Mono«ResponseEntity«string»»:
type: object
title: Mono«ResponseEntity«string»»
description: O1 identities for managed entities
items:
type: string
- name:
- type: string
- description: identity of the ric
policyTypes:
type: array
description: supported policy types
items:
type: string
+ ricName:
+ type: string
+ description: identity of the ric
title: RicInfo
ServiceRegistrationInfo:
type: object
ServiceStatus:
type: object
properties:
+ callbackUrl:
+ type: string
+ description: callback for notifying of RIC recovery
keepAliveIntervalSeconds:
type: integer
format: int64
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
+ * 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 = "Policy server";
- static final String DESCRIPTION = "This page lists all the rest apis for Policy server.";
+ 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";
static final String RESOURCES_PATH = "classpath:/META-INF/resources/";
static final String WEBJARS_PATH = RESOURCES_PATH + "webjars/";
import reactor.core.publisher.Mono;
/**
- * Factory for A1 clients that supports four different protocol versions of the A1 api.
+ * Factory for A1 clients that supports four different protocol versions of the
+ * A1 api.
*/
public class A1ClientFactory {
* 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.
+ * 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.
+ * 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.
+ * @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) //
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
+import org.springframework.http.ResponseEntity;
+import org.springframework.lang.Nullable;
import org.springframework.web.reactive.function.client.WebClient;
+import org.springframework.web.reactive.function.client.WebClient.RequestHeadersSpec;
import reactor.core.publisher.Mono;
public class AsyncRestClient {
private final WebClient client;
private final String baseUrl;
- public class AsyncRestClientException extends Exception {
-
- private static final long serialVersionUID = 1L;
-
- public AsyncRestClientException(String message) {
- super(message);
- }
- }
-
public AsyncRestClient(String baseUrl) {
this.client = WebClient.create(baseUrl);
this.baseUrl = baseUrl;
}
- public Mono<String> post(String uri, String body) {
+ public Mono<ResponseEntity<String>> postForEntity(String uri, @Nullable String body) {
logger.debug("POST uri = '{}{}''", baseUrl, uri);
- return client.post() //
+ Mono<String> bodyProducer = body != null ? Mono.just(body) : Mono.empty();
+ RequestHeadersSpec<?> request = client.post() //
.uri(uri) //
.contentType(MediaType.APPLICATION_JSON) //
- .bodyValue(body) //
- .retrieve() //
- .onStatus(HttpStatus::isError,
- response -> Mono.error(new AsyncRestClientException(response.statusCode().toString()))) //
- .bodyToMono(String.class) //
- .defaultIfEmpty("");
+ .body(bodyProducer, String.class);
+ return retrieve(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) {
logger.debug("POST (auth) uri = '{}{}''", baseUrl, uri);
- return client.post() //
+ RequestHeadersSpec<?> request = client.post() //
.uri(uri) //
.headers(headers -> headers.setBasicAuth(username, password)) //
.contentType(MediaType.APPLICATION_JSON) //
- .bodyValue(body) //
- .retrieve() //
- .onStatus(HttpStatus::isError,
- response -> Mono.error(new AsyncRestClientException(response.statusCode().toString()))) //
- .bodyToMono(String.class) //
- .defaultIfEmpty("");
+ .bodyValue(body);
+ return retrieve(request) //
+ .flatMap(this::toBody);
}
- public Mono<String> put(String uri, String body) {
+ public Mono<ResponseEntity<String>> putForEntity(String uri, String body) {
logger.debug("PUT uri = '{}{}''", baseUrl, uri);
- return client.put() //
+ RequestHeadersSpec<?> request = client.put() //
.uri(uri) //
.contentType(MediaType.APPLICATION_JSON) //
- .bodyValue(body) //
- .retrieve() //
- .onStatus(HttpStatus::isError,
- response -> Mono.error(new AsyncRestClientException(response.statusCode().toString()))) //
- .bodyToMono(String.class) //
- .defaultIfEmpty("");
+ .bodyValue(body);
+ return retrieve(request);
}
- public Mono<String> get(String uri) {
+ public Mono<String> put(String uri, String body) {
+ return putForEntity(uri, body) //
+ .flatMap(this::toBody);
+ }
+
+ public Mono<ResponseEntity<String>> getForEntity(String uri) {
logger.debug("GET uri = '{}{}''", baseUrl, uri);
- return client.get() //
- .uri(uri) //
- .retrieve() //
- .onStatus(HttpStatus::isError,
- response -> Mono.error(new AsyncRestClientException(response.statusCode().toString()))) //
- .bodyToMono(String.class) //
- .defaultIfEmpty("");
+ RequestHeadersSpec<?> request = client.get().uri(uri);
+ return retrieve(request);
}
- public Mono<String> delete(String uri) {
+ public Mono<String> get(String uri) {
+ return getForEntity(uri) //
+ .flatMap(this::toBody);
+ }
+
+ public Mono<ResponseEntity<String>> deleteForEntity(String uri) {
logger.debug("DELETE uri = '{}{}''", baseUrl, uri);
- return client.delete() //
- .uri(uri) //
- .retrieve() //
- .onStatus(HttpStatus::isError,
- response -> Mono.error(new AsyncRestClientException(response.statusCode().toString()))) //
- .bodyToMono(String.class) //
- .defaultIfEmpty("");
+ RequestHeadersSpec<?> request = client.delete().uri(uri);
+ return retrieve(request);
+ }
+
+ public Mono<String> delete(String uri) {
+ return deleteForEntity(uri) //
+ .flatMap(this::toBody);
}
+
+ private Mono<ResponseEntity<String>> retrieve(RequestHeadersSpec<?> request) {
+ return request.retrieve() //
+ .toEntity(String.class);
+ }
+
+ Mono<String> toBody(ResponseEntity<String> entity) {
+ if (entity.getBody() == null) {
+ return Mono.just("");
+ } else {
+ return Mono.just(entity.getBody());
+ }
+ }
+
}
import reactor.core.publisher.Mono;
@RestController
-@Api(value = "Policy Management API")
+@Api(tags = "A1 Policy Management")
public class PolicyController {
private final Rics rics;
@ApiOperation(value = "Returns policy type schema definitions")
@ApiResponses(
value = {
- @ApiResponse(code = 200, message = "Policy schemas", response = Object.class, responseContainer = "List")})
+ @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(@RequestParam(name = "ric", required = false) String ricName) {
synchronized (this.policyTypes) {
if (ricName == null) {
@GetMapping("/policy_schema")
@ApiOperation(value = "Returns one policy type schema definition")
- @ApiResponses(value = {@ApiResponse(code = 200, message = "Policy schema", response = Object.class)})
+ @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(@RequestParam(name = "id", required = true) String id) {
try {
PolicyType type = policyTypes.getType(id);
@GetMapping("/policy_types")
@ApiOperation(value = "Query policy type names")
@ApiResponses(
- value = {@ApiResponse(
- code = 200,
- message = "Policy type names",
- response = String.class,
- responseContainer = "List")})
+ 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(@RequestParam(name = "ric", required = false) String ricName) {
synchronized (this.policyTypes) {
if (ricName == null) {
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "Policy found", response = Object.class), //
- @ApiResponse(code = 204, message = "Policy is not found")} //
+ @ApiResponse(code = 404, message = "Policy is not found")} //
)
public ResponseEntity<String> getPolicy( //
@RequestParam(name = "instance", required = true) String instance) {
Policy p = policies.getPolicy(instance);
return new ResponseEntity<>(p.json(), HttpStatus.OK);
} catch (ServiceException e) {
- return new ResponseEntity<>(e.getMessage(), HttpStatus.NO_CONTENT);
+ 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)})
+ @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 locked", response = String.class)})
public Mono<ResponseEntity<Object>> deletePolicy( //
@RequestParam(name = "instance", required = true) String id) {
Policy policy = policies.get(id);
@PutMapping(path = "/policy")
@ApiOperation(value = "Put a policy", response = String.class)
- @ApiResponses(value = {@ApiResponse(code = 200, message = "Policy created or updated")})
+ @ApiResponses(
+ value = { //
+ @ApiResponse(code = 201, message = "Policy created"), //
+ @ApiResponse(code = 200, message = "Policy updated"), //
+ @ApiResponse(code = 423, message = "RIC is locked", response = String.class), //
+ @ApiResponse(code = 404, message = "RIC or policy type is not found", response = String.class), //
+ @ApiResponse(code = 405, message = "Change is not allowed", response = String.class)})
public Mono<ResponseEntity<Object>> putPolicy( //
@RequestParam(name = "type", required = true) String typeName, //
@RequestParam(name = "instance", required = true) String instanceId, //
@RequestBody Object jsonBody) {
String jsonString = gson.toJson(jsonBody);
-
Ric ric = rics.get(ricName);
PolicyType type = policyTypes.get(typeName);
if (ric != null && type != null && ric.getState() == Ric.RicState.IDLE) {
.onErrorResume(t -> Mono.just(new ResponseEntity<>(t.getMessage(), HttpStatus.METHOD_NOT_ALLOWED)));
}
- return ric == null && type == null ? Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND))
- : Mono.just(new ResponseEntity<>(HttpStatus.CONFLICT)); // Recovering
+ return ric == null || type == null ? Mono.just(new ResponseEntity<>(HttpStatus.NOT_FOUND))
+ : Mono.just(new ResponseEntity<>(HttpStatus.LOCKED)); // Recovering
}
private Mono<Object> validateModifiedPolicy(Policy policy) {
@ApiOperation(value = "Query policies")
@ApiResponses(
value = {
- @ApiResponse(code = 200, message = "Policies", response = PolicyInfo.class, responseContainer = "List")})
+ @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( //
@RequestParam(name = "type", required = false) String type, //
@RequestParam(name = "ric", required = false) String ric, //
@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);
+ }
synchronized (policies) {
Collection<Policy> result = null;
try {
policiesJson = policiesToJson(result);
} catch (ServiceException e) {
- return new ResponseEntity<>(e.getMessage(), HttpStatus.NO_CONTENT);
+ return new ResponseEntity<>(e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
}
return new ResponseEntity<>(policiesJson, HttpStatus.OK);
}
@ApiResponses(
value = { //
@ApiResponse(code = 200, message = "Policy status", response = Object.class), //
- @ApiResponse(code = 204, message = "Policy is not found", response = String.class)} //
+ @ApiResponse(code = 404, message = "Policy is not found", response = String.class)} //
)
public Mono<ResponseEntity<String>> getPolicyStatus( //
@RequestParam(name = "instance", required = true) String instance) {
.flatMap(client -> client.getPolicyStatus(policy)) //
.flatMap(status -> Mono.just(new ResponseEntity<>(status, HttpStatus.OK)));
} catch (ServiceException e) {
- return Mono.just(new ResponseEntity<>(e.getMessage(), HttpStatus.NO_CONTENT));
+ return Mono.just(new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND));
}
}
import java.util.List;
import java.util.Optional;
-import org.oransc.policyagent.configuration.ApplicationConfig;
+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.web.bind.annotation.RestController;
@RestController
-@Api(value = "RIC Management API")
+@Api(tags = "RIC Repository")
public class RicRepositoryController {
@Autowired
private Rics rics;
+ @Autowired
+ PolicyTypes types;
+
private static Gson gson = new GsonBuilder() //
.serializeNulls() //
.create(); //
- @Autowired
- RicRepositoryController(ApplicationConfig appConfig) {
- }
-
/**
* Example: http://localhost:8081/rics?managedElementId=kista_1
*/
}
/**
- * @return a Json array of all RIC data
- * Example: http://localhost:8081/ric
+ * @return a Json array of all RIC data Example: http://localhost:8081/ric
*/
@GetMapping("/rics")
@ApiOperation(value = "Query NearRT RIC information")
@ApiResponses(
value = { //
- @ApiResponse(code = 200, message = "OK", response = RicInfo.class, responseContainer = "List") //
- })
+ @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(
@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<>();
synchronized (rics) {
for (Ric ric : rics.getRics()) {
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
+import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiResponse;
import io.swagger.annotations.ApiResponses;
import org.springframework.web.bind.annotation.RestController;
@RestController
+@Api(tags = "Service registry and supervision")
public class ServiceController {
private final Services services;
@GetMapping("/services")
@ApiOperation(value = "Returns service information")
@ApiResponses(
- value = {@ApiResponse(code = 200, message = "OK", response = ServiceStatus.class, responseContainer = "List")})
+ 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(//
@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<>();
synchronized (this.services) {
for (Service s : this.services.getAll()) {
}
private ServiceStatus toServiceStatus(Service s) {
- return new ServiceStatus(s.getName(), s.getKeepAliveInterval().toSeconds(), s.timeSinceLastPing().toSeconds());
+ return new ServiceStatus(s.getName(), s.getKeepAliveInterval().toSeconds(), s.timeSinceLastPing().toSeconds(),
+ s.getCallbackUrl());
}
@ApiOperation(value = "Register a service")
- @ApiResponses(value = {@ApiResponse(code = 200, message = "OK", response = String.class)})
+ @ApiResponses(
+ value = { //
+ @ApiResponse(code = 200, message = "OK", response = String.class),
+ @ApiResponse(code = 400, message = "Cannot parse the ServiceRegistrationInfo", response = String.class)})
@PutMapping("/service")
public ResponseEntity<String> putService(//
@RequestBody ServiceRegistrationInfo registrationInfo) {
this.services.put(toService(registrationInfo));
return new ResponseEntity<>("OK", HttpStatus.OK);
} catch (Exception e) {
- return new ResponseEntity<>(e.getMessage(), HttpStatus.NO_CONTENT);
+ return new ResponseEntity<>(e.getMessage(), HttpStatus.BAD_REQUEST);
}
}
@ApiOperation(value = "Delete a service")
- @ApiResponses(value = {@ApiResponse(code = 200, message = "OK")})
+ @ApiResponses(
+ value = { //
+ @ApiResponse(code = 204, message = "OK"),
+ @ApiResponse(code = 404, message = "Service not found", response = String.class)})
@DeleteMapping("/services")
public ResponseEntity<String> deleteService(//
@RequestParam(name = "name", required = true) String serviceName) {
removePolicies(service);
return new ResponseEntity<>("OK", HttpStatus.NO_CONTENT);
} catch (Exception e) {
- return new ResponseEntity<>(e.getMessage(), HttpStatus.NO_CONTENT);
+ return new ResponseEntity<>(e.getMessage(), HttpStatus.NOT_FOUND);
}
}
- @ApiOperation(value = "Keep the poilicies alive for a service")
+ @ApiOperation(value = "Keep the policies alive for a service")
@ApiResponses(
- value = {@ApiResponse(code = 200, message = "Policies timeout supervision refreshed"),
+ value = { //
+ @ApiResponse(code = 200, message = "Policies timeout supervision refreshed"),
@ApiResponse(code = 404, message = "The service is not found, needs re-registration")})
@PostMapping("/services/keepalive")
public ResponseEntity<String> keepAliveService(//
@ApiModelProperty(value = "time since last invocation by the service")
public final long timeSincePingSeconds;
- ServiceStatus(String name, long keepAliveIntervalSeconds, long timeSincePingSeconds) {
+ @ApiModelProperty(value = "callback for notifying of RIC recovery")
+ public String callbackUrl;
+
+ ServiceStatus(String name, long keepAliveIntervalSeconds, long timeSincePingSeconds, String callbackUrl) {
this.serviceName = name;
this.keepAliveIntervalSeconds = keepAliveIntervalSeconds;
this.timeSincePingSeconds = timeSincePingSeconds;
+ this.callbackUrl = callbackUrl;
}
}
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 reactor.core.publisher.Mono;
@RestController
+@Api(tags = "Health check")
public class StatusController {
@GetMapping("/status")
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
+/**
+ * The class fetched incoming requests from DMAAP on regular intervals. Each
+ * received request is proceesed by DmaapMessageHandler.
+ */
@Component
public class DmaapMessageConsumer implements Runnable {
* limitations under the License.
* ========================LICENSE_END===================================
*/
-
package org.oransc.policyagent.dmaap;
import com.google.gson.Gson;
import org.onap.dmaap.mr.client.MRBatchingPublisher;
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.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 MRBatchingPublisher dmaapClient;
private final AsyncRestClient agentClient;
Mono<String> createTask(String msg) {
try {
DmaapRequestMessage dmaapRequestMessage = gson.fromJson(msg, ImmutableDmaapRequestMessage.class);
-
return this.invokePolicyAgent(dmaapRequestMessage) //
- .onErrorResume(t -> handleAgentCallError(t, msg, dmaapRequestMessage)) //
- .flatMap(response -> sendDmaapResponse(response, dmaapRequestMessage, HttpStatus.OK));
+ .onErrorResume(t -> handleAgentCallError(t, dmaapRequestMessage)) //
+ .flatMap(
+ response -> sendDmaapResponse(response.getBody(), dmaapRequestMessage, response.getStatusCode()));
} catch (Exception e) {
logger.warn("Received unparsable message from DMAAP: {}", msg);
- return Mono.error(e);
+ return Mono.error(e); // Cannot make any response
}
}
- private Mono<String> handleAgentCallError(Throwable t, String origianalMessage,
- DmaapRequestMessage dmaapRequestMessage) {
+ private Mono<ResponseEntity<String>> handleAgentCallError(Throwable t, DmaapRequestMessage dmaapRequestMessage) {
logger.debug("Agent call failed: {}", t.getMessage());
- if (t instanceof ServiceException) {
- String errorMessage = prepareBadOperationErrorMessage(t, origianalMessage);
- return sendDmaapResponse(errorMessage, dmaapRequestMessage, HttpStatus.NOT_FOUND) //
- .flatMap(notUsed -> Mono.empty());
- } else {
- return sendDmaapResponse(t.toString(), dmaapRequestMessage, HttpStatus.NOT_FOUND) //
- .flatMap(notUsed -> Mono.empty());
+ HttpStatus status = HttpStatus.NOT_FOUND;
+ String errorMessage = t.getMessage();
+ if (t instanceof WebClientResponseException) {
+ WebClientResponseException exception = (WebClientResponseException) t;
+ status = exception.getStatusCode();
+ errorMessage = exception.getResponseBodyAsString();
}
+ return sendDmaapResponse(errorMessage, dmaapRequestMessage, status) //
+ .flatMap(notUsed -> Mono.empty());
}
- private String prepareBadOperationErrorMessage(Throwable t, String origianalMessage) {
- String badOperation = origianalMessage.substring(origianalMessage.indexOf("operation\":\"") + 12,
- origianalMessage.indexOf(",\"url\":"));
- String errorMessage = t.getMessage().replace("null", badOperation);
- return errorMessage;
- }
-
- private Mono<String> invokePolicyAgent(DmaapRequestMessage dmaapRequestMessage) {
+ private Mono<ResponseEntity<String>> invokePolicyAgent(DmaapRequestMessage dmaapRequestMessage) {
DmaapRequestMessage.Operation operation = dmaapRequestMessage.operation();
- if (operation == null) {
- return Mono.error(new ServiceException("Not implemented operation: " + operation));
- }
- Mono<String> result = null;
+
String uri = dmaapRequestMessage.url();
- switch (operation) {
- case DELETE:
- result = agentClient.delete(uri);
- break;
- case GET:
- result = agentClient.get(uri);
- break;
- case PUT:
- result = agentClient.put(uri, payload(dmaapRequestMessage));
- break;
- case POST:
- result = agentClient.post(uri, payload(dmaapRequestMessage));
- break;
- default:
- // Nothing, can never get here.
+ 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));
}
- return result;
+
}
private String payload(DmaapRequestMessage message) {
private Mono<String> sendDmaapResponse(String response, DmaapRequestMessage dmaapRequestMessage,
HttpStatus status) {
- return getDmaapResponseMessage(dmaapRequestMessage, response, status) //
+ return createDmaapResponseMessage(dmaapRequestMessage, response, status) //
.flatMap(this::sendToDmaap) //
.onErrorResume(this::handleResponseCallError);
}
}
private Mono<String> handleResponseCallError(Throwable t) {
- logger.debug("Failed to send respons to DMaaP: {}", t.getMessage());
+ logger.debug("Failed to respond: {}", t.getMessage());
return Mono.empty();
}
- private Mono<String> getDmaapResponseMessage(DmaapRequestMessage dmaapRequestMessage, String response,
+ private Mono<String> createDmaapResponseMessage(DmaapRequestMessage dmaapRequestMessage, String response,
HttpStatus status) {
DmaapResponseMessage dmaapResponseMessage = ImmutableDmaapResponseMessage.builder() //
.status(status.toString()) //
.timestamp(dmaapRequestMessage.timestamp()) //
.build();
String str = gson.toJson(dmaapResponseMessage);
-
return Mono.just(str);
}
import static org.assertj.core.api.Assertions.assertThat;
import static org.awaitility.Awaitility.await;
+import static org.junit.jupiter.api.Assertions.assertTrue;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
-import java.io.IOException;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
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.RicConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
-import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
-import org.springframework.http.HttpStatus.Series;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
-import org.springframework.http.client.ClientHttpResponse;
import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.web.client.ResponseErrorHandler;
import org.springframework.web.client.RestTemplate;
+import org.springframework.web.reactive.function.client.WebClientResponseException;
+
+import reactor.core.publisher.Mono;
+import reactor.test.StepVerifier;
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT)
@LocalServerPort
private int port;
- private final RestTemplate restTemplate = new RestTemplate();
-
- public class RestTemplateResponseErrorHandler implements ResponseErrorHandler {
-
- @Override
- public boolean hasError(ClientHttpResponse httpResponse) throws IOException {
- return (httpResponse.getStatusCode().series() == Series.CLIENT_ERROR
- || httpResponse.getStatusCode().series() == Series.SERVER_ERROR);
- }
-
- @Override
- public void handleError(ClientHttpResponse httpResponse) throws IOException {
- System.out.println("Error " + httpResponse.toString());
- }
- }
-
- private void setRestErrorhandler() {
- restTemplate.setErrorHandler(new RestTemplateResponseErrorHandler());
- }
-
@BeforeEach
public void reset() {
rics.clear();
@Test
public void testGetRics() throws Exception {
addRic("kista_1");
- String url = baseUrl() + "/rics";
- String rsp = this.restTemplate.getForObject(url, String.class);
- System.out.println(rsp);
+ this.addPolicyType("type1", "kista_1");
+ String url = "/rics?policyType=type1";
+ String rsp = restClient().get(url).block();
assertThat(rsp).contains("kista_1");
- url = baseUrl() + "/rics?policyType=STD_PolicyModelUnconstrained_0.2.0";
- rsp = this.restTemplate.getForObject(url, String.class);
- assertThat(rsp).isEqualTo("[]");
+ // Non existing policy type
+ url = "/rics?policyType=XXXX";
+ testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
}
@Test
String managedElementId = "kista_1";
addRic(ricName, managedElementId);
- String url = baseUrl() + "/ric?managedElementId=" + managedElementId;
- String rsp = this.restTemplate.getForObject(url, String.class);
-
+ 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);
}
- @Test
- public void testGetRicForManagedElementThatDoesNotExist() throws Exception {
- this.setRestErrorhandler();
- String url = baseUrl() + "/ric?managedElementId=kista_1";
- ResponseEntity<String> entity = this.restTemplate.getForEntity(url, String.class);
- assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
+ private String putPolicyUrl(String serviceName, String ricName, String policyTypeName, String policyInstanceId) {
+ String url = "/policy?type=" + policyTypeName + "&instance=" + policyInstanceId + "&ric=" + ricName
+ + "&service=" + serviceName;
+ return url;
}
@Test
putService(serviceName);
addPolicyType(policyTypeName, ricName);
- String url = baseUrl() + "/policy?type=" + policyTypeName + "&instance=" + policyInstanceId + "&ric=" + ricName
- + "&service=" + serviceName;
- final String json = jsonString();
+ String url = putPolicyUrl(serviceName, ricName, policyTypeName, policyInstanceId);
+ final String policyBody = jsonString();
this.rics.getRic(ricName).setState(Ric.RicState.IDLE);
- this.restTemplate.put(url, createJsonHttpEntity(json));
+ restClient().put(url, policyBody).block();
Policy policy = policies.getPolicy(policyInstanceId);
assertThat(policy).isNotNull();
assertThat(policy.ownerServiceName()).isEqualTo(serviceName);
assertThat(policy.ric().name()).isEqualTo("ric1");
- url = baseUrl() + "/policies";
- String rsp = this.restTemplate.getForObject(url, String.class);
+ url = "/policies";
+ String rsp = restClient().get(url).block();
assertThat(rsp.contains(policyInstanceId)).isTrue();
+ // 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);
+ 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.IDLE);
}
@Test
// In this case service is attempted to be changed
this.addRic("ric1");
this.addRic("ricXXX");
-
this.addPolicy("instance1", "type1", "service1", "ric1");
- this.setRestErrorhandler();
- String urlWrongRic = baseUrl() + "/policy?type=type1&instance=instance1&ric=ricXXX&service=service1";
- ResponseEntity<String> entity = this.putForEntity(urlWrongRic, jsonString());
- assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.METHOD_NOT_ALLOWED);
- Policy policy = policies.getPolicy("instance1");
- assertThat(policy.ric().name()).isEqualTo("ric1"); // Not changed
+ // Try change ric1 -> ricXXX
+ String urlWrongRic = putPolicyUrl("service1", "ricXXX", "type1", "instance1");
+ testErrorCode(restClient().put(urlWrongRic, jsonString()), HttpStatus.METHOD_NOT_ALLOWED);
}
@Test
public void testGetPolicy() throws Exception {
- String url = baseUrl() + "/policy?instance=id";
+ String url = "/policy?instance=id";
Policy policy = addPolicy("id", "typeName", "service1", "ric1");
{
- String rsp = this.restTemplate.getForObject(url, String.class);
+ String rsp = restClient().get(url).block();
assertThat(rsp).isEqualTo(policy.json());
}
{
policies.remove(policy);
- ResponseEntity<String> rsp = this.restTemplate.getForEntity(url, String.class);
- assertThat(rsp.getStatusCodeValue()).isEqualTo(HttpStatus.NO_CONTENT.value());
+ testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
}
}
@Test
public void testDeletePolicy() throws Exception {
- String url = baseUrl() + "/policy?instance=id";
addPolicy("id", "typeName", "service1", "ric1");
assertThat(policies.size()).isEqualTo(1);
- this.restTemplate.delete(url);
+ String url = "/policy?instance=id";
+ ResponseEntity<String> entity = restClient().deleteForEntity(url).block();
+ assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NO_CONTENT);
assertThat(policies.size()).isEqualTo(0);
+
+ // Delete a non existing policy
+ testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
}
@Test
addPolicyType("type1", "ric1");
addPolicyType("type2", "ric2");
- String url = baseUrl() + "/policy_schemas";
- String rsp = this.restTemplate.getForObject(url, String.class);
- System.out.println("*** " + rsp);
+ String url = "/policy_schemas";
+ String rsp = this.restClient().get(url).block();
assertThat(rsp).contains("type1");
assertThat(rsp).contains("[{\"title\":\"type2\"}");
List<String> info = parseSchemas(rsp);
assertThat(info.size()).isEqualTo(2);
- url = baseUrl() + "/policy_schemas?ric=ric1";
- rsp = this.restTemplate.getForObject(url, String.class);
+ url = "/policy_schemas?ric=ric1";
+ rsp = restClient().get(url).block();
assertThat(rsp).contains("type1");
info = parseSchemas(rsp);
assertThat(info.size()).isEqualTo(1);
+
+ // Get schema for non existing RIC
+ url = "/policy_schemas?ric=ric1XXX";
+ testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
}
@Test
addPolicyType("type1", "ric1");
addPolicyType("type2", "ric2");
- String url = baseUrl() + "/policy_schema?id=type1";
- String rsp = this.restTemplate.getForObject(url, String.class);
+ String url = "/policy_schema?id=type1";
+ String rsp = restClient().get(url).block();
System.out.println(rsp);
assertThat(rsp).contains("type1");
assertThat(rsp).contains("title");
+
+ // Get non existing schema
+ url = "/policy_schema?id=type1XX";
+ testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
}
@Test
addPolicyType("type1", "ric1");
addPolicyType("type2", "ric2");
- String url = baseUrl() + "/policy_types";
- String rsp = this.restTemplate.getForObject(url, String.class);
+ String url = "/policy_types";
+ String rsp = restClient().get(url).block();
assertThat(rsp).isEqualTo("[\"type2\",\"type1\"]");
- url = baseUrl() + "/policy_types?ric=ric1";
- rsp = this.restTemplate.getForObject(url, String.class);
+ 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
public void testGetPolicies() throws Exception {
reset();
- String url = baseUrl() + "/policies";
addPolicy("id1", "type1", "service1");
- String rsp = this.restTemplate.getForObject(url, String.class);
+ String url = "/policies";
+ String rsp = restClient().get(url).block();
System.out.println(rsp);
List<PolicyInfo> info = parseList(rsp, PolicyInfo.class);
assertThat(info).size().isEqualTo(1);
addPolicy("id2", "type1", "service2");
addPolicy("id3", "type2", "service1");
- String url = baseUrl() + "/policies?type=type1";
- String rsp = this.restTemplate.getForObject(url, String.class);
+ String url = "/policies?type=type1";
+ String rsp = restClient().get(url).block();
System.out.println(rsp);
assertThat(rsp).contains("id1");
assertThat(rsp).contains("id2");
assertThat(rsp.contains("id3")).isFalse();
- url = baseUrl() + "/policies?type=type1&service=service2";
- rsp = this.restTemplate.getForObject(url, String.class);
+ url = "/policies?type=type1&service=service2";
+ rsp = restClient().get(url).block();
System.out.println(rsp);
assertThat(rsp.contains("id1")).isFalse();
assertThat(rsp).contains("id2");
assertThat(rsp.contains("id3")).isFalse();
+
+ // 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
// PUT
putService("name");
- // GET
- String url = baseUrl() + "/services?serviceName=name";
- String rsp = this.restTemplate.getForObject(url, String.class);
+ // GET one service
+ String url = "/services?name=name";
+ String rsp = restClient().get(url).block();
List<ServiceStatus> info = parseList(rsp, ServiceStatus.class);
assertThat(info.size()).isEqualTo(1);
ServiceStatus status = info.iterator().next();
assertThat(status.serviceName).isEqualTo("name");
// GET (all)
- url = baseUrl() + "/services";
- rsp = this.restTemplate.getForObject(url, String.class);
+ url = "/services";
+ rsp = restClient().get(url).block();
assertThat(rsp.contains("name")).isTrue();
System.out.println(rsp);
// Keep alive
- url = baseUrl() + "/services/keepalive?name=name";
- ResponseEntity<String> entity = this.restTemplate.postForEntity(url, null, String.class);
+ url = "/services/keepalive?name=name";
+ ResponseEntity<String> entity = restClient().postForEntity(url, null).block();
assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.OK);
- // DELETE
+ // DELETE service
assertThat(services.size()).isEqualTo(1);
- url = baseUrl() + "/services?name=name";
- this.restTemplate.delete(url);
+ url = "/services?name=name";
+ restClient().delete(url).block();
assertThat(services.size()).isEqualTo(0);
// Keep alive, no registerred service
- url = baseUrl() + "/services/keepalive?name=name";
- setRestErrorhandler();
- entity = this.restTemplate.postForEntity(url, null, String.class);
- assertThat(entity.getStatusCode()).isEqualTo(HttpStatus.NOT_FOUND);
+ testErrorCode(restClient().post("/services/keepalive?name=name", ""), HttpStatus.NOT_FOUND);
+
+ // PUT servive with crap payload
+ testErrorCode(restClient().put("/service", "junk"), HttpStatus.BAD_REQUEST);
+
+ // GET non existing servive
+ testErrorCode(restClient().get("/services?name=XXX"), HttpStatus.NOT_FOUND);
}
@Test
addPolicy("id", "typeName", "service1", "ric1");
assertThat(policies.size()).isEqualTo(1);
- String url = baseUrl() + "/policy_status?instance=id";
- String rsp = this.restTemplate.getForObject(url, String.class);
+ String url = "/policy_status?instance=id";
+ String rsp = restClient().get(url).block();
assertThat(rsp.equals("OK")).isTrue();
+
+ // GET non existing policy status
+ url = "/policy_status?instance=XXX";
+ testErrorCode(restClient().get(url), HttpStatus.NOT_FOUND);
}
private Policy addPolicy(String id, String typeName, String service, String ric) throws ServiceException {
}
private void putService(String name) {
- String url = baseUrl() + "/service";
- HttpEntity<String> entity = createJsonHttpEntity(createServiceJson(name));
- this.restTemplate.put(url, entity);
+ String url = "/service";
+ restClient().put(url, createServiceJson(name)).block();
}
private String baseUrl() {
private void putPolicy(String name) {
String putUrl = baseUrl + "/policy?type=type1&instance=" + name + "&ric=ric1&service=service1";
- this.restTemplate.put(putUrl, createJsonHttpEntity("{}"));
+ restTemplate.put(putUrl, createJsonHttpEntity("{}"));
}
private void deletePolicy(String name) {
String deleteUrl = baseUrl + "/policy?instance=" + name;
- this.restTemplate.delete(deleteUrl);
+ restTemplate.delete(deleteUrl);
}
}
System.out.println("Concurrency test took " + Duration.between(startTime, Instant.now()));
}
+ private AsyncRestClient restClient() {
+ return new AsyncRestClient(baseUrl());
+ }
+
+ private void testErrorCode(Mono<?> request, HttpStatus expStatus) {
+ StepVerifier.create(request) //
+ .expectSubscription() //
+ .expectErrorMatches(t -> checkWebClientError(t, expStatus)) //
+ .verify();
+ }
+
+ private boolean checkWebClientError(Throwable t, HttpStatus expStatus) {
+ assertTrue(t instanceof WebClientResponseException);
+ WebClientResponseException e = (WebClientResponseException) t;
+ assertThat(e.getStatusCode()).isEqualTo(expStatus);
+ return true;
+ }
+
private MockA1Client getA1Client(String ricName) throws ServiceException {
return a1ClientFactory.getOrCreateA1Client(ricName);
}
return new HttpEntity<String>(content, headers);
}
- private ResponseEntity<String> putForEntity(String url, String jsonBody) {
- return restTemplate.exchange(url, HttpMethod.PUT, createJsonHttpEntity(jsonBody), String.class);
- }
-
private static <T> List<T> parseList(String jsonString, Class<T> clazz) {
List<T> result = new ArrayList<>();
JsonArray jsonArr = JsonParser.parseString(jsonString).getAsJsonArray();
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
-import org.oransc.policyagent.clients.AsyncRestClient.AsyncRestClientException;
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;
mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
Mono<String> returnedMono = clientUnderTest.get(REQUEST_URL);
- StepVerifier.create(returnedMono).expectErrorMatches(throwable -> throwable instanceof AsyncRestClientException)
- .verify();
+ StepVerifier.create(returnedMono)
+ .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
}
@Test
mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
Mono<String> returnedMono = clientUnderTest.put(REQUEST_URL, TEST_JSON);
- StepVerifier.create(returnedMono).expectErrorMatches(throwable -> throwable instanceof AsyncRestClientException)
- .verify();
+ StepVerifier.create(returnedMono)
+ .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
}
@Test
mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
Mono<String> returnedMono = clientUnderTest.delete(REQUEST_URL);
- StepVerifier.create(returnedMono).expectErrorMatches(throwable -> throwable instanceof AsyncRestClientException)
- .verify();
+ StepVerifier.create(returnedMono)
+ .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
}
@Test
mockWebServer.enqueue(new MockResponse().setResponseCode(ERROR_CODE));
Mono<String> returnedMono = clientUnderTest.post(REQUEST_URL, TEST_JSON);
- StepVerifier.create(returnedMono).expectErrorMatches(throwable -> throwable instanceof AsyncRestClientException)
- .verify();
+ StepVerifier.create(returnedMono)
+ .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
}
@Test
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 AsyncRestClientException)
- .verify();
+ StepVerifier.create(returnedMono)
+ .expectErrorMatches(throwable -> throwable instanceof WebClientResponseException).verify();
}
}
RicConfigUpdate update =
appConfigUnderTest.setConfiguration(Arrays.asList(RIC_CONFIG_1), null, null).blockFirst();
assertEquals(RicConfigUpdate.Type.ADDED, update.getType());
- assertTrue(appConfigUnderTest.getRicConfigs().contains(RIC_CONFIG_1), "Ric not added to configuraions.");
+ 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.");
import org.oransc.policyagent.repository.PolicyType;
import org.oransc.policyagent.utils.LoggingUtils;
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;
return gson.toJson(dmaapRequestMessage(operation));
}
+ private Mono<ResponseEntity<String>> okResponse() {
+ ResponseEntity<String> entity = new ResponseEntity<>("OK", HttpStatus.OK);
+ return Mono.just(entity);
+ }
+
@Test
public void testMessageParsing() {
String message = dmaapInputMessage(Operation.DELETE);
@Test
public void successfulDelete() throws IOException {
- doReturn(Mono.just("OK")).when(agentClient).delete(anyString());
+ doReturn(okResponse()).when(agentClient).deleteForEntity(anyString());
doReturn(1).when(dmaapClient).send(anyString());
doReturn(new MRPublisherResponse()).when(dmaapClient).sendBatchWithResponse();
.expectNext("OK") //
.verifyComplete(); //
- verify(agentClient).delete(URL);
+ verify(agentClient).deleteForEntity(URL);
verifyNoMoreInteractions(agentClient);
verify(dmaapClient).send(anyString());
@Test
public void successfulGet() throws IOException {
- doReturn(Mono.just("OK")).when(agentClient).get(anyString());
+ doReturn(okResponse()).when(agentClient).getForEntity(anyString());
doReturn(1).when(dmaapClient).send(anyString());
doReturn(new MRPublisherResponse()).when(dmaapClient).sendBatchWithResponse();
.expectNext("OK") //
.verifyComplete(); //
- verify(agentClient).get(URL);
+ verify(agentClient).getForEntity(URL);
verifyNoMoreInteractions(agentClient);
verify(dmaapClient).send(anyString());
@Test
public void successfulPut() throws IOException {
- doReturn(Mono.just("OK")).when(agentClient).put(anyString(), anyString());
+ doReturn(okResponse()).when(agentClient).putForEntity(anyString(), anyString());
doReturn(1).when(dmaapClient).send(anyString());
doReturn(new MRPublisherResponse()).when(dmaapClient).sendBatchWithResponse();
.expectNext("OK") //
.verifyComplete(); //
- verify(agentClient).put(URL, payloadAsString());
+ verify(agentClient).putForEntity(URL, payloadAsString());
verifyNoMoreInteractions(agentClient);
verify(dmaapClient).send(anyString());
@Test
public void successfulPost() throws IOException {
- doReturn(Mono.just("OK")).when(agentClient).post(anyString(), anyString());
+ doReturn(okResponse()).when(agentClient).postForEntity(anyString(), anyString());
doReturn(1).when(dmaapClient).send(anyString());
doReturn(new MRPublisherResponse()).when(dmaapClient).sendBatchWithResponse();
.expectNext("OK") //
.verifyComplete(); //
- verify(agentClient).post(URL, payloadAsString());
+ verify(agentClient).postForEntity(URL, payloadAsString());
verifyNoMoreInteractions(agentClient);
verify(dmaapClient).send(anyString());
@Test
public void exceptionWhenCallingPolicyAgent_thenNotFoundResponse() throws IOException {
- String errorCause = "Refused";
- doReturn(Mono.error(new Exception(errorCause))).when(agentClient).put(anyString(), any());
+ WebClientResponseException except = new WebClientResponseException(400, "Refused", null, null, null, null);
+ doReturn(Mono.error(except)).when(agentClient).putForEntity(anyString(), any());
doReturn(1).when(dmaapClient).send(anyString());
doReturn(new MRPublisherResponse()).when(dmaapClient).sendBatchWithResponse();
.expectSubscription() //
.verifyComplete(); //
- verify(agentClient).put(anyString(), anyString());
+ verify(agentClient).putForEntity(anyString(), anyString());
verifyNoMoreInteractions(agentClient);
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(dmaapClient).send(captor.capture());
String actualMessage = captor.getValue();
- assertThat(actualMessage.contains(HttpStatus.NOT_FOUND + "\",\"message\":\"java.lang.Exception: " + errorCause))
- .isTrue();
+ assertThat(actualMessage.contains(HttpStatus.BAD_REQUEST.toString())).isTrue();
verify(dmaapClient).sendBatchWithResponse();
verifyNoMoreInteractions(dmaapClient);
ArgumentCaptor<String> captor = ArgumentCaptor.forClass(String.class);
verify(dmaapClient).send(captor.capture());
String actualMessage = captor.getValue();
- assertThat(actualMessage
- .contains(HttpStatus.NOT_FOUND + "\",\"message\":\"Not implemented operation: " + badOperation)).isTrue();
+ assertThat(actualMessage.contains(HttpStatus.NOT_FOUND + "\",\"message\":\"Not implemented operation:"))
+ .isTrue();
verify(dmaapClient).sendBatchWithResponse();
verifyNoMoreInteractions(dmaapClient);