diff options
Diffstat (limited to 'runtime-controlloop')
45 files changed, 1953 insertions, 2092 deletions
diff --git a/runtime-controlloop/pom.xml b/runtime-controlloop/pom.xml index ab72deb91..e436451ff 100644 --- a/runtime-controlloop/pom.xml +++ b/runtime-controlloop/pom.xml @@ -44,5 +44,66 @@ <artifactId>policy-clamp-models</artifactId> <version>${project.version}</version> </dependency> + <dependency> + <groupId>com.fasterxml.jackson.module</groupId> + <artifactId>jackson-module-jsonSchema</artifactId> + <version>${version.jackson}</version> + <exclusions> + <exclusion> + <groupId>javax.validation</groupId> + <artifactId>validation-api</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <exclusions> + <exclusion> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-json</artifactId> + </exclusion> + </exclusions> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-security</artifactId> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-validation</artifactId> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-boot-starter</artifactId> + <version>${version.springfox}</version> + </dependency> + <dependency> + <groupId>io.springfox</groupId> + <artifactId>springfox-swagger-ui</artifactId> + <scope>runtime</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <scope>test</scope> + </dependency> </dependencies> + + <build> + <plugins> + <plugin> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-maven-plugin</artifactId> + <executions> + <execution> + <goals> + <goal>repackage</goal> + </goals> + <phase>package</phase> + </execution> + </executions> + </plugin> + </plugins> + </build> </project> diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/Application.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/Application.java new file mode 100644 index 000000000..a2b6f62d4 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/Application.java @@ -0,0 +1,32 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningHandler.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningHandler.java deleted file mode 100644 index 74975e768..000000000 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningHandler.java +++ /dev/null @@ -1,78 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.commissioning; - -import java.io.IOException; -import java.util.Set; -import javax.ws.rs.core.Response; -import lombok.Getter; -import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler; -import org.onap.policy.clamp.controlloop.runtime.commissioning.rest.CommissioningController; -import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; -import org.onap.policy.common.utils.services.Registry; -import org.onap.policy.models.base.PfModelRuntimeException; - -/** - * This class handles commissioning of control loop definitions. - */ -public final class CommissioningHandler extends ControlLoopHandler { - - @Getter - private CommissioningProvider provider; - - /** - * Gets the CommissioningHandler. - * - * @return CommissioningHandler - */ - public static CommissioningHandler getInstance() { - return Registry.get(CommissioningHandler.class.getName()); - } - - /** - * Create a handler. - * - * @param controlLoopParameters the parameters for access to the database - */ - public CommissioningHandler(ClRuntimeParameterGroup controlLoopParameters) { - super(controlLoopParameters.getDatabaseProviderParameters()); - } - - @Override - public Set<Class<?>> getProviderClasses() { - return Set.of(CommissioningController.class); - } - - @Override - public void startProviders() { - provider = new CommissioningProvider(getDatabaseProviderParameters()); - } - - @Override - public void stopProviders() { - try { - provider.close(); - } catch (IOException e) { - throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR, - "an error has occured while stopping commissioning providers", e); - } - } -} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java index 5bbf6a079..f291c4e89 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProvider.java @@ -20,6 +20,11 @@ package org.onap.policy.clamp.controlloop.runtime.commissioning; +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.module.jsonSchema.JsonSchema; +import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper; import java.io.Closeable; import java.io.IOException; import java.util.ArrayList; @@ -31,21 +36,29 @@ import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.collections4.MapUtils; import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider; import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.provider.PolicyModelsProvider; import org.onap.policy.models.provider.PolicyModelsProviderFactory; -import org.onap.policy.models.provider.PolicyModelsProviderParameters; +import org.onap.policy.models.tosca.authorative.concepts.ToscaCapabilityType; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.onap.policy.models.tosca.authorative.concepts.ToscaDataType; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; +import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeType; +import org.onap.policy.models.tosca.authorative.concepts.ToscaPolicyType; +import org.onap.policy.models.tosca.authorative.concepts.ToscaRelationshipType; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplates; +import org.onap.policy.models.tosca.authorative.concepts.ToscaTopologyTemplate; import org.onap.policy.models.tosca.authorative.concepts.ToscaTypedEntityFilter; +import org.springframework.stereotype.Component; /** * This class provides the create, read and delete actions on Commissioning of Control Loop concepts in the database to * the callers. */ +@Component public class CommissioningProvider implements Closeable { public static final String CONTROL_LOOP_NODE_TYPE = "org.onap.policy.clamp.controlloop.ControlLoop"; @@ -56,19 +69,20 @@ public class CommissioningProvider implements Closeable { /** * Create a commissioning provider. - * @param databaseProviderParameters parameters for database access + * + * @param controlLoopParameters the parameters for access to the database * @throws PfModelRuntimeException on errors creating the database provider */ - public CommissioningProvider(PolicyModelsProviderParameters databaseProviderParameters) { + public CommissioningProvider(ClRuntimeParameterGroup controlLoopParameters) { try { modelsProvider = new PolicyModelsProviderFactory() - .createPolicyModelsProvider(databaseProviderParameters); + .createPolicyModelsProvider(controlLoopParameters.getDatabaseProviderParameters()); } catch (PfModelException e) { throw new PfModelRuntimeException(e); } try { - clProvider = new ControlLoopProvider(databaseProviderParameters); + clProvider = new ControlLoopProvider(controlLoopParameters.getDatabaseProviderParameters()); } catch (PfModelException e) { throw new PfModelRuntimeException(e); } @@ -78,6 +92,7 @@ public class CommissioningProvider implements Closeable { public void close() throws IOException { try { modelsProvider.close(); + clProvider.close(); } catch (PfModelException e) { throw new IOException("error closing modelsProvider", e); } @@ -203,4 +218,49 @@ public class CommissioningProvider implements Closeable { serviceTemplates.setServiceTemplates(modelsProvider.getServiceTemplateList(name, version)); return serviceTemplates.getServiceTemplates().get(0); } + + /** + * Get the requested json schema. + * + * @param section section of the tosca service template to get schema for + * @return the specified tosca service template or section Json Schema + * @throws PfModelException on errors with retrieving the classes + * @throws JsonProcessingException on errors generating the schema + */ + public String getToscaServiceTemplateSchema(String section) throws PfModelException, JsonProcessingException { + ObjectMapper mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + SchemaFactoryWrapper visitor = new SchemaFactoryWrapper(); + + switch (section) { + case "data_types": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaDataType.class), visitor); + break; + case "capability_types": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaCapabilityType.class), visitor); + break; + case "node_types": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaNodeType.class), visitor); + break; + case "relationship_types": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaRelationshipType.class), visitor); + break; + case "policy_types": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaPolicyType.class), visitor); + break; + case "topology_template": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaTopologyTemplate.class), visitor); + break; + case "node_templates": + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaNodeTemplate.class), visitor); + break; + default: + mapper.acceptJsonFormatVisitor(mapper.constructType(ToscaServiceTemplate.class), visitor); + } + + JsonSchema jsonSchema = visitor.finalSchema(); + String response = mapper.writerWithDefaultPrettyPrinter().writeValueAsString(jsonSchema); + + return response; + } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningController.java deleted file mode 100644 index ebfbbd5ee..000000000 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningController.java +++ /dev/null @@ -1,412 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.commissioning.rest; - -import io.swagger.annotations.ApiOperation; -import io.swagger.annotations.ApiParam; -import io.swagger.annotations.ApiResponse; -import io.swagger.annotations.ApiResponses; -import io.swagger.annotations.Authorization; -import io.swagger.annotations.Extension; -import io.swagger.annotations.ExtensionProperty; -import io.swagger.annotations.ResponseHeader; -import java.util.List; -import java.util.UUID; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.POST; -import javax.ws.rs.Path; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; -import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse; -import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningHandler; -import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; -import org.onap.policy.clamp.controlloop.runtime.main.rest.RestController; -import org.onap.policy.models.base.PfModelException; -import org.onap.policy.models.base.PfModelRuntimeException; -import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; -import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Class to provide REST end points for creating, deleting, querying commissioned control loops. - */ -public class CommissioningController extends RestController { - - private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class); - - private final CommissioningProvider provider; - - /** - * create Commissioning Controller. - */ - public CommissioningController() { - this.provider = CommissioningHandler.getInstance().getProvider(); - } - - /** - * Creates a control loop definition. - * - * @param requestId request ID used in ONAP logging - * @param body the body of control loop following TOSCA definition - * @return a response - */ - // @formatter:off - @POST - @Path("/commission") - @ApiOperation( - value = "Commissions control loop definitions", - notes = "Commissions control loop definitions, returning the commissioned control loop definition IDs", - response = CommissioningResponse.class, - tags = {"Control Loop Commissioning API"}, - authorizations = @Authorization(value = AUTHORIZATION_TYPE), - responseHeaders = { - @ResponseHeader( - name = VERSION_MINOR_NAME, - description = VERSION_MINOR_DESCRIPTION, - response = String.class), - @ResponseHeader( - name = VERSION_PATCH_NAME, - description = VERSION_PATCH_DESCRIPTION, - response = String.class), - @ResponseHeader( - name = VERSION_LATEST_NAME, - description = VERSION_LATEST_DESCRIPTION, - response = String.class), - @ResponseHeader( - name = REQUEST_ID_NAME, - description = REQUEST_ID_HDR_DESCRIPTION, - response = UUID.class) - }, - extensions = { - @Extension - ( - name = EXTENSION_NAME, - properties = { - @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), - @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) - } - ) - } - ) - @ApiResponses( - value = { - @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), - @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), - @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) - } - ) - // @formatter:on - public Response create(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Entity Body of Control Loop", required = true) ToscaServiceTemplate body) { - - try { - CommissioningResponse response = provider.createControlLoopDefinitions(body); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) - .build(); - - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Commissioning of the control loops failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp); - } - - } - - /** - * Deletes a control loop definition. - * - * @param requestId request ID used in ONAP logging - * @param name the name of the control loop definition to delete - * @param version the version of the control loop definition to delete - * @return a response - */ - // @formatter:off - @DELETE - @Path("/commission") - @ApiOperation(value = "Delete a commissioned control loop", - notes = "Deletes a Commissioned Control Loop, returning optional error details", - response = CommissioningResponse.class, - tags = {"Clamp Control Loop Commissioning API"}, - authorizations = @Authorization(value = AUTHORIZATION_TYPE), - responseHeaders = { - @ResponseHeader( - name = VERSION_MINOR_NAME, - description = VERSION_MINOR_DESCRIPTION, - response = String.class), - @ResponseHeader( - name = VERSION_PATCH_NAME, - description = VERSION_PATCH_DESCRIPTION, - response = String.class), - @ResponseHeader( - name = VERSION_LATEST_NAME, - description = VERSION_LATEST_DESCRIPTION, - response = String.class), - @ResponseHeader( - name = REQUEST_ID_NAME, - description = REQUEST_ID_HDR_DESCRIPTION, - response = UUID.class)}, - extensions = { - @Extension - ( - name = EXTENSION_NAME, - properties = { - @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), - @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) - } - ) - } - ) - @ApiResponses( - value = { - @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), - @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), - @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) - } - ) - // @formatter:on - public Response delete(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name, - @ApiParam(value = "Control Loop definition version", required = true) @QueryParam("version") String version) { - - try { - CommissioningResponse response = provider.deleteControlLoopDefinition(name, version); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) - .build(); - - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Decommisssioning of control loop failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp); - } - - } - - /** - * Queries details of all or specific control loop definitions. - * - * @param requestId request ID used in ONAP logging - * @param name the name of the control loop definition to get, null for all definitions - * @param version the version of the control loop definition to get, null for all definitions - * @return the control loop definitions - */ - // @formatter:off - @GET - @Path("/commission") - @ApiOperation(value = "Query details of the requested commissioned control loop definitions", - notes = "Queries details of the requested commissioned control loop definitions, " - + "returning all control loop details", - response = ToscaNodeTemplate.class, - tags = {"Clamp Control Loop Commissioning API"}, - authorizations = @Authorization(value = AUTHORIZATION_TYPE), - responseHeaders = { - @ResponseHeader( - name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, - response = String.class), - @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, - response = String.class), - @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, - response = String.class), - @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, - response = UUID.class)}, - extensions = { - @Extension - ( - name = EXTENSION_NAME, - properties = { - @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), - @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) - } - ) - } - ) - @ApiResponses( - value = { - @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), - @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), - @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) - } - ) - // @formatter:on - public Response query(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name, - @ApiParam(value = "Control Loop definition version", required = true) @QueryParam("version") String version) { - - try { - List<ToscaNodeTemplate> response = provider.getControlLoopDefinitions(name, version); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) - .build(); - - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Get of control loop definitions failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp); - } - - } - - /** - * Retrieves the Tosca Service Template. - * - * @param requestId request ID used in ONAP logging - * @param name the name of the tosca service template to retrieve - * @param version the version of the tosca service template to get - * @return the specified tosca service template - */ - // @formatter:off - @GET - @Path("/commission/toscaservicetemplate") - @ApiOperation(value = "Query details of the requested tosca service templates", - notes = "Queries details of the requested commissioned tosca service template, " - + "returning all tosca service template details", - response = ToscaServiceTemplate.class, - tags = {"Clamp Control Loop Commissioning API"}, - authorizations = @Authorization(value = AUTHORIZATION_TYPE), - responseHeaders = { - @ResponseHeader( - name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, - response = String.class), - @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, - response = String.class), - @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, - response = String.class), - @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, - response = UUID.class)}, - extensions = { - @Extension - ( - name = EXTENSION_NAME, - properties = { - @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), - @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) - } - ) - } - ) - @ApiResponses( - value = { - @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), - @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), - @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) - } - ) - // @formatter:on - public Response queryToscaServiceTemplate( - @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Tosca service template name", required = true) @QueryParam("name") String name, - @ApiParam(value = "Tosca service template version", required = true) @QueryParam("version") String version) { - - try { - var response = provider.getToscaServiceTemplate(name, version); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) - .build(); - - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Get of tosca service template failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp); - } - - } - - /** - * Queries the elements of a specific control loop. - * - * @param requestId request ID used in ONAP logging - * @param name the name of the control loop definition to get - * @param version the version of the control loop definition to get - * @return the control loop element definitions - */ - // @formatter:off - @GET - @Path("/commission/elements") - @ApiOperation(value = "Query details of the requested commissioned control loop element definitions", - notes = "Queries details of the requested commissioned control loop element definitions, " - + "returning all control loop elements' details", - response = ToscaNodeTemplate.class, - tags = {"Clamp Control Loop Commissioning API"}, - authorizations = @Authorization(value = AUTHORIZATION_TYPE), - responseHeaders = { - @ResponseHeader( - name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, - response = String.class), - @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, - response = String.class), - @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, - response = String.class), - @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, - response = UUID.class)}, - extensions = { - @Extension - ( - name = EXTENSION_NAME, - properties = { - @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), - @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) - } - ) - } - ) - @ApiResponses( - value = { - @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), - @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), - @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) - } - ) - // @formatter:on - public Response queryElements(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name, - @ApiParam(value = "Control Loop definition version", required = true) @QueryParam("version") String version) { - - try { - List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version); - // Prevent ambiguous queries with multiple returns - if (nodeTemplate.size() > 1) { - var resp = new CommissioningResponse(); - resp.setErrorDetails("Multiple ControlLoops are not supported"); - return returnResponse(Response.Status.NOT_ACCEPTABLE, requestId, resp); - } - - List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0)); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) - .build(); - - } catch (PfModelRuntimeException | PfModelException e) { - LOGGER.warn("Get of control loop element definitions failed", e); - var resp = new CommissioningResponse(); - resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return returnResponse(e.getErrorResponse().getResponseCode(), requestId, resp); - } - - } - - private Response returnResponse(Response.Status status, UUID requestId, CommissioningResponse resp) { - return addLoggingHeaders(addVersionControlHeaders(Response.status(status)), requestId).entity(resp).build(); - } -} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/AafConfiguration.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/AafConfiguration.java new file mode 100644 index 000000000..4483fbd1b --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/AafConfiguration.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * ONAP CLAMP + * ================================================================================ + * Copyright (C) 2017-2018 AT&T Intellectual Property. 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.onap.policy.clamp.controlloop.runtime.config; + +import javax.servlet.Filter; +import org.onap.policy.clamp.controlloop.runtime.main.web.ControlLoopAafFilter; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +@Configuration +@Profile("clamp-aaf-authentication") +public class AafConfiguration { + + /** + * Method to return Aaf filter. + * + * @return Filter + */ + @Bean + public Filter aafFilter() { + return new ControlLoopAafFilter(); + } + +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/ActivatorConfig.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/ActivatorConfig.java new file mode 100644 index 000000000..1d6b92e77 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/ActivatorConfig.java @@ -0,0 +1,46 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.config; + +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; +import org.onap.policy.clamp.controlloop.runtime.main.startstop.ClRuntimeActivator; +import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class ActivatorConfig { + + /** + * Create and start ClRuntimeActivator. + * + * @param clRuntimeParameterGroup the parameters for the control loop runtime service + * @param supervisionHandler the SupervisionHandler + * @return ClRuntimeActivator + */ + @Bean + public ClRuntimeActivator clRuntimeActivator(ClRuntimeParameterGroup clRuntimeParameterGroup, + SupervisionHandler supervisionHandler) { + var clRuntimeActivator = new ClRuntimeActivator(clRuntimeParameterGroup, supervisionHandler); + clRuntimeActivator.start(); + return clRuntimeActivator; + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/CoderHttpMesageConverter.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/CoderHttpMesageConverter.java new file mode 100644 index 000000000..cdd6ea73b --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/CoderHttpMesageConverter.java @@ -0,0 +1,74 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.config; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.nio.charset.StandardCharsets; +import javax.ws.rs.core.Response; +import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException; +import org.onap.policy.common.utils.coder.Coder; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.coder.StandardYamlCoder; +import org.springframework.http.HttpInputMessage; +import org.springframework.http.HttpOutputMessage; +import org.springframework.http.MediaType; +import org.springframework.http.converter.AbstractHttpMessageConverter; +import org.springframework.http.converter.HttpMessageNotReadableException; +import org.springframework.http.converter.HttpMessageNotWritableException; + +public class CoderHttpMesageConverter<T> extends AbstractHttpMessageConverter<T> { + + private Coder coder; + + public CoderHttpMesageConverter(String type) { + super(new MediaType("application", type, StandardCharsets.UTF_8)); + this.coder = "json".equals(type) ? new StandardCoder() : new StandardYamlCoder(); + } + + @Override + protected boolean supports(Class<?> clazz) { + return true; + } + + @Override + protected T readInternal(Class<? extends T> clazz, HttpInputMessage inputMessage) + throws IOException, HttpMessageNotReadableException { + try (var is = new InputStreamReader(inputMessage.getBody(), StandardCharsets.UTF_8)) { + return coder.decode(is, clazz); + } catch (CoderException e) { + throw new ControlLoopRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e); + } + } + + @Override + protected void writeInternal(T t, HttpOutputMessage outputMessage) + throws IOException, HttpMessageNotWritableException { + try (var writer = new OutputStreamWriter(outputMessage.getBody(), StandardCharsets.UTF_8)) { + coder.encode(writer, t); + } catch (CoderException e) { + throw new ControlLoopRuntimeException(Response.Status.BAD_REQUEST, e.getMessage(), e); + } + } + +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/ConverterConfiguration.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/ConverterConfiguration.java new file mode 100644 index 000000000..ee0461994 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/ConverterConfiguration.java @@ -0,0 +1,36 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.config; + +import java.util.List; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; + +@Configuration +public class ConverterConfiguration implements WebMvcConfigurer { + + @Override + public void extendMessageConverters(List<HttpMessageConverter<?>> converters) { + converters.add(new CoderHttpMesageConverter<>("yaml")); + converters.add(new CoderHttpMesageConverter<>("json")); + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/FilterConfig.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/FilterConfig.java new file mode 100644 index 000000000..d58553ae4 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/FilterConfig.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.config; + +import org.onap.policy.clamp.controlloop.runtime.main.web.RequestResponseLoggingFilter; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FilterConfig { + + /** + * Logging Filter configuration. + * + * @return FilterRegistrationBean + */ + @Bean + public FilterRegistrationBean<RequestResponseLoggingFilter> loggingFilter() { + FilterRegistrationBean<RequestResponseLoggingFilter> registrationBean = new FilterRegistrationBean<>(); + + registrationBean.setFilter(new RequestResponseLoggingFilter()); + registrationBean.addUrlPatterns("/onap/controlloop/v2/*"); + + return registrationBean; + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/PropertiesConfig.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/PropertiesConfig.java new file mode 100644 index 000000000..04bd35da3 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/PropertiesConfig.java @@ -0,0 +1,38 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.config; + +import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterHandler; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class PropertiesConfig { + + @Bean + public ClRuntimeParameterGroup clRuntimeParameterGroup(@Value("${runtime.file}") String file) + throws ControlLoopException { + return new ClRuntimeParameterHandler().getParameters(file); + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/SecurityConfig.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/SecurityConfig.java new file mode 100644 index 000000000..846944ea2 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/SecurityConfig.java @@ -0,0 +1,47 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.config; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; + +@Configuration +public class SecurityConfig extends WebSecurityConfigurerAdapter { + + @Value("${security.enable-csrf:true}") + private boolean csrfEnabled = true; + + @Override + protected void configure(HttpSecurity http) throws Exception { + // @formatter:off + http.authorizeRequests() + .antMatchers().authenticated() + .anyRequest().authenticated() + .and().httpBasic(); + // @formatter:on + + if (!csrfEnabled) { + http.csrf().disable(); + } + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/SpringFoxConfig.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/SpringFoxConfig.java new file mode 100644 index 000000000..d8c703397 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/config/SpringFoxConfig.java @@ -0,0 +1,45 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.config; + +import org.onap.policy.clamp.controlloop.runtime.main.rest.MonitoringQueryController; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; + +@Configuration +public class SpringFoxConfig { + + /** + * Docket Spring Fox Config. + * + * @return Docket + */ + @Bean + public Docket api() { + return new Docket(DocumentationType.SWAGGER_2).select() + .apis(RequestHandlerSelectors.basePackage(MonitoringQueryController.class.getPackageName())) + .paths(PathSelectors.any()).build(); + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProvider.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProvider.java index f458d7c51..c01a0b989 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProvider.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProvider.java @@ -39,6 +39,7 @@ import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand; import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationResponse; import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; import org.onap.policy.common.parameters.BeanValidationResult; import org.onap.policy.common.parameters.ObjectValidationResult; @@ -46,29 +47,35 @@ import org.onap.policy.common.parameters.ValidationResult; import org.onap.policy.common.parameters.ValidationStatus; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; -import org.onap.policy.models.provider.PolicyModelsProviderParameters; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; +import org.springframework.stereotype.Component; /** * This class is dedicated to the Instantiation of Commissioned control loop. */ +@Component public class ControlLoopInstantiationProvider implements Closeable { private final ControlLoopProvider controlLoopProvider; private final CommissioningProvider commissioningProvider; + private final SupervisionHandler supervisionHandler; private static final Object lockit = new Object(); /** * Create a instantiation provider. * - * @param databaseProviderParameters the parameters for database access + * @param controlLoopParameters the parameters for access to the database + * @param commissioningProvider CommissioningProvider + * @param supervisionHandler SupervisionHandler * @throws PfModelRuntimeException on errors creating a provider */ - public ControlLoopInstantiationProvider(PolicyModelsProviderParameters databaseProviderParameters) { + public ControlLoopInstantiationProvider(ClRuntimeParameterGroup controlLoopParameters, + CommissioningProvider commissioningProvider, SupervisionHandler supervisionHandler) { + this.commissioningProvider = commissioningProvider; + this.supervisionHandler = supervisionHandler; try { - controlLoopProvider = new ControlLoopProvider(databaseProviderParameters); - commissioningProvider = new CommissioningProvider(databaseProviderParameters); + controlLoopProvider = new ControlLoopProvider(controlLoopParameters.getDatabaseProviderParameters()); } catch (PfModelException e) { throw new PfModelRuntimeException(e); } @@ -93,7 +100,7 @@ public class ControlLoopInstantiationProvider implements Closeable { var checkControlLoop = controlLoopProvider.getControlLoop(controlLoop.getKey().asIdentifier()); if (checkControlLoop != null) { throw new PfModelException(Response.Status.BAD_REQUEST, - controlLoop.getKey().asIdentifier() + " already defined"); + controlLoop.getKey().asIdentifier() + " already defined"); } } BeanValidationResult validationResult = validateControlLoops(controlLoops); @@ -105,7 +112,7 @@ public class ControlLoopInstantiationProvider implements Closeable { var response = new InstantiationResponse(); response.setAffectedControlLoops(controlLoops.getControlLoopList().stream() - .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList())); + .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList())); return response; } @@ -128,7 +135,7 @@ public class ControlLoopInstantiationProvider implements Closeable { var response = new InstantiationResponse(); response.setAffectedControlLoops(controlLoops.getControlLoopList().stream() - .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList())); + .map(cl -> cl.getKey().asIdentifier()).collect(Collectors.toList())); return response; } @@ -148,18 +155,18 @@ public class ControlLoopInstantiationProvider implements Closeable { var subResult = new BeanValidationResult("entry " + controlLoop.getDefinition().getName(), controlLoop); List<ToscaNodeTemplate> toscaNodeTemplates = commissioningProvider.getControlLoopDefinitions( - controlLoop.getDefinition().getName(), controlLoop.getDefinition().getVersion()); + controlLoop.getDefinition().getName(), controlLoop.getDefinition().getVersion()); if (toscaNodeTemplates.isEmpty()) { subResult.addResult(new ObjectValidationResult("ControlLoop", controlLoop.getDefinition().getName(), - ValidationStatus.INVALID, "Commissioned control loop definition not FOUND")); + ValidationStatus.INVALID, "Commissioned control loop definition not FOUND")); } else if (toscaNodeTemplates.size() > 1) { subResult.addResult(new ObjectValidationResult("ControlLoop", controlLoop.getDefinition().getName(), - ValidationStatus.INVALID, "Commissioned control loop definition not VALID")); + ValidationStatus.INVALID, "Commissioned control loop definition not VALID")); } else { List<ToscaNodeTemplate> clElementDefinitions = - commissioningProvider.getControlLoopElementDefinitions(toscaNodeTemplates.get(0)); + commissioningProvider.getControlLoopElementDefinitions(toscaNodeTemplates.get(0)); // @formatter:off Map<String, ToscaConceptIdentifier> definitions = clElementDefinitions @@ -185,7 +192,7 @@ public class ControlLoopInstantiationProvider implements Closeable { * @return the validation result */ private ValidationResult validateDefinition(Map<String, ToscaConceptIdentifier> definitions, - ToscaConceptIdentifier definition) { + ToscaConceptIdentifier definition) { var result = new BeanValidationResult("entry " + definition.getName(), definition); ToscaConceptIdentifier identifier = definitions.get(definition.getName()); if (identifier == null) { @@ -214,12 +221,12 @@ public class ControlLoopInstantiationProvider implements Closeable { for (ControlLoop controlLoop : controlLoops) { if (!ControlLoopState.UNINITIALISED.equals(controlLoop.getState())) { throw new PfModelException(Response.Status.BAD_REQUEST, - "Control Loop State is still " + controlLoop.getState()); + "Control Loop State is still " + controlLoop.getState()); } } response.setAffectedControlLoops(Collections - .singletonList(controlLoopProvider.deleteControlLoop(name, version).getKey().asIdentifier())); + .singletonList(controlLoopProvider.deleteControlLoop(name, version).getKey().asIdentifier())); } return response; } @@ -248,7 +255,7 @@ public class ControlLoopInstantiationProvider implements Closeable { * @throws ControlLoopException on ordered state invalid */ public InstantiationResponse issueControlLoopCommand(InstantiationCommand command) - throws ControlLoopException, PfModelException { + throws ControlLoopException, PfModelException { if (command.getOrderedState() == null) { throw new ControlLoopException(Status.BAD_REQUEST, "ordered state invalid or not specified on command"); @@ -264,7 +271,6 @@ public class ControlLoopInstantiationProvider implements Closeable { controlLoopProvider.updateControlLoops(controlLoops); } - var supervisionHandler = SupervisionHandler.getInstance(); supervisionHandler.triggerControlLoopSupervision(command.getControlLoopIdentifierList()); var response = new InstantiationResponse(); response.setAffectedControlLoops(command.getControlLoopIdentifierList()); diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java deleted file mode 100644 index 67fd9455e..000000000 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java +++ /dev/null @@ -1,79 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.instantiation; - -import java.io.IOException; -import java.util.Set; -import javax.ws.rs.core.Response; -import lombok.Getter; -import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler; -import org.onap.policy.clamp.controlloop.runtime.instantiation.rest.InstantiationController; -import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; -import org.onap.policy.common.utils.services.Registry; -import org.onap.policy.models.base.PfModelRuntimeException; - -/** - * This class handles instantiation of control loop instances. - * - * <p/>It is effectively a singleton that is started at system start - */ -public final class InstantiationHandler extends ControlLoopHandler { - - @Getter - private ControlLoopInstantiationProvider controlLoopInstantiationProvider; - - /** - * Gets the InstantiationHandler. - * - * @return InstantiationHandler - */ - public static InstantiationHandler getInstance() { - return Registry.get(InstantiationHandler.class.getName()); - } - - /** - * Create a handler. - * - * @param controlLoopParameters the parameters for access to the database - */ - public InstantiationHandler(ClRuntimeParameterGroup controlLoopParameters) { - super(controlLoopParameters.getDatabaseProviderParameters()); - } - - @Override - public Set<Class<?>> getProviderClasses() { - return Set.of(InstantiationController.class); - } - - @Override - public void startProviders() { - controlLoopInstantiationProvider = new ControlLoopInstantiationProvider(getDatabaseProviderParameters()); - } - - @Override - public void stopProviders() { - try { - controlLoopInstantiationProvider.close(); - } catch (IOException e) { - throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR, e.getMessage()); - } - } -} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterHandler.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterHandler.java index a463ad171..bcf1124d2 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterHandler.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/parameters/ClRuntimeParameterHandler.java @@ -23,7 +23,6 @@ package org.onap.policy.clamp.controlloop.runtime.main.parameters; import java.io.File; import javax.ws.rs.core.Response; import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; -import org.onap.policy.clamp.controlloop.runtime.main.startstop.ClRuntimeCommandLineArguments; import org.onap.policy.common.parameters.ValidationResult; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; @@ -39,37 +38,33 @@ public class ClRuntimeParameterHandler { /** * Read the parameters from the parameter file. * - * @param arguments the arguments passed to control loop runtime + * @param path the path passed to control loop runtime * @return the parameters read from the configuration file * @throws ControlLoopException on parameter exceptions */ - public ClRuntimeParameterGroup getParameters(final ClRuntimeCommandLineArguments arguments) - throws ControlLoopException { + public ClRuntimeParameterGroup getParameters(final String path) throws ControlLoopException { ClRuntimeParameterGroup clRuntimeParameterGroup = null; // Read the parameters try { // Read the parameters from JSON - File file = new File(arguments.getFullConfigurationFilePath()); + File file = new File(path); clRuntimeParameterGroup = CODER.decode(file, ClRuntimeParameterGroup.class); } catch (final CoderException e) { - throw new ControlLoopException( - Response.Status.NOT_ACCEPTABLE, "error reading parameters from \"" - + arguments.getConfigurationFilePath() + "\"\n" + "(" + e.getClass().getSimpleName() + ")", - e); + throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, + "error reading parameters from \"" + path + "\"\n" + "(" + e.getClass().getSimpleName() + ")", e); } // The JSON processing returns null if there is an empty file if (clRuntimeParameterGroup == null) { - throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, - "no parameters found in \"" + arguments.getConfigurationFilePath() + "\""); + throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, "no parameters found in \"" + path + "\""); } // validate the parameters final ValidationResult validationResult = clRuntimeParameterGroup.validate(); if (!validationResult.isValid()) { - throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, "validation error(s) on parameters from \"" - + arguments.getConfigurationFilePath() + "\"\n" + validationResult.getResult()); + throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, + "validation error(s) on parameters from \"" + path + "\"\n" + validationResult.getResult()); } return clRuntimeParameterGroup; diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java new file mode 100644 index 000000000..b50e7a0ed --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/CommissioningController.java @@ -0,0 +1,506 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.main.rest; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.databind.PropertyNamingStrategies; +import com.fasterxml.jackson.module.jsonSchema.JsonSchema; +import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper; +import io.swagger.annotations.ApiOperation; +import io.swagger.annotations.ApiParam; +import io.swagger.annotations.ApiResponse; +import io.swagger.annotations.ApiResponses; +import io.swagger.annotations.Authorization; +import io.swagger.annotations.Extension; +import io.swagger.annotations.ExtensionProperty; +import io.swagger.annotations.ResponseHeader; +import java.util.List; +import java.util.UUID; +import javax.ws.rs.core.Response.Status; +import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse; +import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; +import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController; +import org.onap.policy.models.base.PfModelException; +import org.onap.policy.models.base.PfModelRuntimeException; +import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; +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.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +/** + * Class to provide REST end points for creating, deleting, querying commissioned control loops. + */ +@RestController +public class CommissioningController extends AbstractRestController { + + private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class); + + private final CommissioningProvider provider; + + /** + * Create Commissioning Controller. + * + * @param provider the CommissioningProvider + */ + public CommissioningController(CommissioningProvider provider) { + this.provider = provider; + } + + /** + * Creates a control loop definition. + * + * @param requestId request ID used in ONAP logging + * @param body the body of control loop following TOSCA definition + * @return a response + */ + // @formatter:off + @PostMapping(value = "/commission", + consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}, + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) + @ApiOperation( + value = "Commissions control loop definitions", + notes = "Commissions control loop definitions, returning the commissioned control loop definition IDs", + response = CommissioningResponse.class, + tags = {"Control Loop Commissioning API"}, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, + description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = VERSION_PATCH_NAME, + description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = VERSION_LATEST_NAME, + description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = REQUEST_ID_NAME, + description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class) + }, + extensions = { + @Extension + ( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public ResponseEntity<CommissioningResponse> create( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Entity Body of Control Loop", required = true) @RequestBody ToscaServiceTemplate body) { + try { + return ResponseEntity.ok().body(provider.createControlLoopDefinitions(body)); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Commissioning of the control loops failed", e); + var resp = new CommissioningResponse(); + resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } + + } + + /** + * Deletes a control loop definition. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the control loop definition to delete + * @param version the version of the control loop definition to delete + * @return a response + */ + // @formatter:off + @DeleteMapping(value = "/commission", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) + @ApiOperation(value = "Delete a commissioned control loop", + notes = "Deletes a Commissioned Control Loop, returning optional error details", + response = CommissioningResponse.class, + tags = {"Clamp Control Loop Commissioning API"}, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, + description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = VERSION_PATCH_NAME, + description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = VERSION_LATEST_NAME, + description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader( + name = REQUEST_ID_NAME, + description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension + ( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public ResponseEntity<CommissioningResponse> delete( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop definition name", required = true) @RequestParam( + value = "name") String name, + @ApiParam( + value = "Control Loop definition version", + required = true) @RequestParam("version") String version) { + + try { + return ResponseEntity.ok().body(provider.deleteControlLoopDefinition(name, version)); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Decommisssioning of control loop failed", e); + var resp = new CommissioningResponse(); + resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } + + } + + /** + * Queries details of all or specific control loop definitions. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the control loop definition to get, null for all definitions + * @param version the version of the control loop definition to get, null for all definitions + * @return the control loop definitions + */ + // @formatter:off + @GetMapping(value = "/commission", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) + @ApiOperation(value = "Query details of the requested commissioned control loop definitions", + notes = "Queries details of the requested commissioned control loop definitions, " + + "returning all control loop details", + response = ToscaNodeTemplate.class, + tags = {"Clamp Control Loop Commissioning API"}, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension + ( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public ResponseEntity<?> query( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop definition name", required = false) @RequestParam( + value = "name", + required = false) String name, + @ApiParam(value = "Control Loop definition version", required = false) @RequestParam( + value = "version", + required = false) String version) { + + try { + return ResponseEntity.ok().body(provider.getControlLoopDefinitions(name, version)); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Get of control loop definitions failed", e); + var resp = new CommissioningResponse(); + resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } + + } + + /** + * Retrieves the Tosca Service Template. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the tosca service template to retrieve + * @param version the version of the tosca service template to get + * @return the specified tosca service template + */ + // @formatter:off + @GetMapping(value = "/commission/toscaservicetemplate", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) + @ApiOperation(value = "Query details of the requested tosca service templates", + notes = "Queries details of the requested commissioned tosca service template, " + + "returning all tosca service template details", + response = ToscaServiceTemplate.class, + tags = {"Clamp Control Loop Commissioning API"}, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension + ( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public ResponseEntity<?> queryToscaServiceTemplate( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Tosca service template name", required = false) @RequestParam( + value = "name", + required = false) String name, + @ApiParam(value = "Tosca service template version", required = true) @RequestParam( + value = "version", + required = false) String version) { + + try { + return ResponseEntity.ok().body(provider.getToscaServiceTemplate(name, version)); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Get of tosca service template failed", e); + var resp = new CommissioningResponse(); + resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } + + } + + /** + * Retrieves the Json Schema for the specified Tosca Service Template. + * + * @param requestId request ID used in ONAP logging + * @param section section of the tosca service template to get schema for + * @return the specified tosca service template or section Json Schema + */ + // @formatter:off + @GetMapping(value = "/commission/toscaServiceTemplateSchema", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) + @ApiOperation(value = "Query details of the requested tosca service template json schema", + notes = "Queries details of the requested commissioned tosca service template json schema, " + + "returning all tosca service template json schema details", + response = ToscaServiceTemplate.class, + tags = {"Clamp Control Loop Commissioning API"}, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension + ( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public ResponseEntity<?> queryToscaServiceTemplateJsonSchema( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Section of Template schema is desired for", required = false) @RequestParam( + value = "section", + required = false, defaultValue = "all") String section) { + try { + return ResponseEntity.ok().body(provider.getToscaServiceTemplateSchema(section)); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Get of tosca service template json schema failed", e); + var resp = new CommissioningResponse(); + resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } catch (JsonProcessingException e) { + LOGGER.warn("Get of tosca service template json schema failed", e); + var resp = new CommissioningResponse(); + resp.setErrorDetails(e.getMessage()); + return ResponseEntity.status(Status.BAD_REQUEST.getStatusCode()).body(resp); + } + } + + /** + * Queries the elements of a specific control loop. + * + * @param requestId request ID used in ONAP logging + * @param name the name of the control loop definition to get + * @param version the version of the control loop definition to get + * @return the control loop element definitions + */ + // @formatter:off + @GetMapping(value = "/commission/elements", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) + @ApiOperation(value = "Query details of the requested commissioned control loop element definitions", + notes = "Queries details of the requested commissioned control loop element definitions, " + + "returning all control loop elements' details", + response = ToscaNodeTemplate.class, + tags = {"Clamp Control Loop Commissioning API"}, + authorizations = @Authorization(value = AUTHORIZATION_TYPE), + responseHeaders = { + @ResponseHeader( + name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION, + response = String.class), + @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION, + response = String.class), + @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION, + response = UUID.class)}, + extensions = { + @Extension + ( + name = EXTENSION_NAME, + properties = { + @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION), + @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE) + } + ) + } + ) + @ApiResponses( + value = { + @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE), + @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE), + @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE) + } + ) + // @formatter:on + public ResponseEntity<?> queryElements( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop definition name", required = false) @RequestParam( + value = "name", + required = false) String name, + @ApiParam(value = "Control Loop definition version", required = true) @RequestParam( + value = "version", + required = false) String version) { + + try { + List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version); + // Prevent ambiguous queries with multiple returns + if (nodeTemplate.size() > 1) { + var resp = new CommissioningResponse(); + resp.setErrorDetails("Multiple ControlLoops are not supported"); + return ResponseEntity.status(HttpStatus.NOT_ACCEPTABLE).body(resp); + } + + List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0)); + return ResponseEntity.ok().body(response); + + } catch (PfModelRuntimeException | PfModelException e) { + LOGGER.warn("Get of control loop element definitions failed", e); + var resp = new CommissioningResponse(); + resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); + } + + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/rest/InstantiationController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java index ea36c71fb..aba585e29 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/rest/InstantiationController.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/InstantiationController.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.controlloop.runtime.instantiation.rest; +package org.onap.policy.clamp.controlloop.runtime.main.rest; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @@ -29,32 +29,33 @@ import io.swagger.annotations.Extension; import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.ResponseHeader; import java.util.UUID; -import javax.ws.rs.DELETE; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.POST; -import javax.ws.rs.PUT; -import javax.ws.rs.Path; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; -import javax.ws.rs.core.Response.Status; import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops; import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand; import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationResponse; import org.onap.policy.clamp.controlloop.runtime.instantiation.ControlLoopInstantiationProvider; -import org.onap.policy.clamp.controlloop.runtime.instantiation.InstantiationHandler; -import org.onap.policy.clamp.controlloop.runtime.main.rest.RestController; +import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.errors.concepts.ErrorResponseInfo; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +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.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; /** * Class to provide REST end points for creating, deleting, query and commanding a control loop definition. */ -public class InstantiationController extends RestController { +@RestController +public class InstantiationController extends AbstractRestController { private static final Logger LOGGER = LoggerFactory.getLogger(InstantiationController.class); @@ -62,10 +63,12 @@ public class InstantiationController extends RestController { private final ControlLoopInstantiationProvider provider; /** - * create Instantiation Controller. + * Create Instantiation Controller. + * + * @param provider the ControlLoopInstantiationProvider */ - public InstantiationController() { - this.provider = InstantiationHandler.getInstance().getControlLoopInstantiationProvider(); + public InstantiationController(ControlLoopInstantiationProvider provider) { + this.provider = provider; } /** @@ -76,8 +79,9 @@ public class InstantiationController extends RestController { * @return a response */ // @formatter:off - @POST - @Path("/instantiation") + @PostMapping(value = "/instantiation", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}, + consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) @ApiOperation( value = "Commissions control loop definitions", notes = "Commissions control loop definitions, returning the control loop IDs", @@ -121,18 +125,18 @@ public class InstantiationController extends RestController { } ) // @formatter:on - public Response create( - @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Entity Body of Control Loop", required = true) ControlLoops controlLoops) { + public ResponseEntity<InstantiationResponse> create( + @RequestHeader(name = REQUEST_ID_NAME, required = false) + @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Entity Body of Control Loop", required = true) + @RequestBody ControlLoops controlLoops) { try { - InstantiationResponse response = provider.createControlLoops(controlLoops); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) - .build(); + return ResponseEntity.ok().body(provider.createControlLoops(controlLoops)); } catch (PfModelRuntimeException | PfModelException e) { LOGGER.warn("creation of control loop failed", e); - return createInstantiationErrorResponse(e, requestId); + return createInstantiationErrorResponse(e); } } @@ -145,8 +149,8 @@ public class InstantiationController extends RestController { * @return the control loops */ // @formatter:off - @GET - @Path("/instantiation") + @GetMapping(value = "/instantiation", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) @ApiOperation(value = "Query details of the requested control loops", notes = "Queries details of the requested control loops, returning all control loop details", response = ControlLoops.class, @@ -183,20 +187,20 @@ public class InstantiationController extends RestController { } ) // @formatter:on - public Response query( - @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name, - @ApiParam(value = "Control Loop definition version", - required = true) @QueryParam("version") String version) { + public ResponseEntity<?> query( + @RequestHeader(name = REQUEST_ID_NAME, required = false) + @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop definition name", required = false) + @RequestParam(value = "name", required = false) String name, + @ApiParam(value = "Control Loop definition version", required = false) + @RequestParam(value = "version", required = false) String version) { try { - var response = provider.getControlLoops(name, version); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) - .build(); + return ResponseEntity.ok().body(provider.getControlLoops(name, version)); } catch (PfModelRuntimeException | PfModelException e) { LOGGER.warn("commisssioning of control loop failed", e); - return createInstantiationErrorResponse(e, requestId); + return createInstantiationErrorResponse(e); } } @@ -209,8 +213,9 @@ public class InstantiationController extends RestController { * @return a response */ // @formatter:off - @PUT - @Path("/instantiation") + @PutMapping(value = "/instantiation", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}, + consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) @ApiOperation( value = "Updates control loop definitions", notes = "Updates control loop definitions, returning the updated control loop definition IDs", @@ -256,18 +261,18 @@ public class InstantiationController extends RestController { } ) // @formatter:on - public Response update( - @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Entity Body of Control Loop", required = true) ControlLoops controlLoops) { + public ResponseEntity<InstantiationResponse> update( + @RequestHeader(name = REQUEST_ID_NAME, required = false) + @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Entity Body of Control Loop", required = true) + @RequestBody ControlLoops controlLoops) { try { - InstantiationResponse response = provider.updateControlLoops(controlLoops); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) - .build(); + return ResponseEntity.ok().body(provider.updateControlLoops(controlLoops)); } catch (PfModelRuntimeException | PfModelException e) { LOGGER.warn("update of control loops failed", e); - return createInstantiationErrorResponse(e, requestId); + return createInstantiationErrorResponse(e); } } @@ -280,8 +285,8 @@ public class InstantiationController extends RestController { * @return a response */ // @formatter:off - @DELETE - @Path("/instantiation") + @DeleteMapping(value = "/instantiation", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) @ApiOperation(value = "Delete a control loop", notes = "Deletes a control loop, returning optional error details", response = InstantiationResponse.class, @@ -326,20 +331,20 @@ public class InstantiationController extends RestController { ) // @formatter:on - public Response delete( - @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name, - @ApiParam(value = "Control Loop definition version", required = true) - @QueryParam("version") String version) { + public ResponseEntity<InstantiationResponse> delete( + @RequestHeader(name = REQUEST_ID_NAME, required = false) + @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop definition name", required = true) + @RequestParam("name") String name, + @ApiParam(value = "Control Loop definition version") + @RequestParam(value = "version", required = false) String version) { try { - InstantiationResponse response = provider.deleteControlLoop(name, version); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response) - .build(); + return ResponseEntity.ok().body(provider.deleteControlLoop(name, version)); } catch (PfModelRuntimeException | PfModelException e) { LOGGER.warn("delete of control loop failed", e); - return createInstantiationErrorResponse(e, requestId); + return createInstantiationErrorResponse(e); } } @@ -351,8 +356,9 @@ public class InstantiationController extends RestController { * @return the control loop definitions */ // @formatter:off - @PUT - @Path("/instantiation/command") + @PutMapping(value = "/instantiation/command", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}, + consumes = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) @ApiOperation(value = "Issue a command to the requested control loops", notes = "Issues a command to a control loop, ordering a state change on the control loop", response = InstantiationResponse.class, @@ -389,32 +395,30 @@ public class InstantiationController extends RestController { } ) // @formatter:on - public Response issueControlLoopCommand( - @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Entity Body of control loop command", required = true) InstantiationCommand command) { + public ResponseEntity<InstantiationResponse> issueControlLoopCommand( + @RequestHeader(name = REQUEST_ID_NAME, required = false) + @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Entity Body of control loop command", required = true) + @RequestBody InstantiationCommand command) { try { - InstantiationResponse response = provider.issueControlLoopCommand(command); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.ACCEPTED)), requestId) - .entity(response).build(); + return ResponseEntity.accepted().body(provider.issueControlLoopCommand(command)); } catch (PfModelRuntimeException | PfModelException | ControlLoopException e) { LOGGER.warn("creation of control loop failed", e); - return createInstantiationErrorResponse(e, requestId); + return createInstantiationErrorResponse(e); } } /** * create a Instantiation Response from an exception. + * * @param e the error - * @param requestId request ID used in ONAP logging * @return the Instantiation Response */ - private Response createInstantiationErrorResponse(ErrorResponseInfo e, UUID requestId) { + private ResponseEntity<InstantiationResponse> createInstantiationErrorResponse(ErrorResponseInfo e) { var resp = new InstantiationResponse(); resp.setErrorDetails(e.getErrorResponse().getErrorMessage()); - return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), - requestId).entity(resp).build(); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).body(resp); } } - diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java index 7fde5fba3..86531597a 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryController.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/MonitoringQueryController.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.controlloop.runtime.monitoring.rest; +package org.onap.policy.clamp.controlloop.runtime.main.rest; import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiParam; @@ -30,38 +30,39 @@ import io.swagger.annotations.ExtensionProperty; import io.swagger.annotations.ResponseHeader; import java.time.Instant; import java.util.UUID; -import javax.ws.rs.DefaultValue; -import javax.ws.rs.GET; -import javax.ws.rs.HeaderParam; -import javax.ws.rs.Path; -import javax.ws.rs.QueryParam; -import javax.ws.rs.core.Response; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatisticsList; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatisticsList; -import org.onap.policy.clamp.controlloop.runtime.main.rest.RestController; -import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringHandler; +import org.onap.policy.clamp.controlloop.runtime.main.web.AbstractRestController; import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestHeader; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; /** * This class handles REST endpoints for CL Statistics monitoring. */ -public class MonitoringQueryController extends RestController { +@RestController +public class MonitoringQueryController extends AbstractRestController { private static final Logger LOGGER = LoggerFactory.getLogger(MonitoringQueryController.class); private final MonitoringProvider provider; /** * Create Monitoring Controller. + * + * @param provider the MonitoringProvider */ - public MonitoringQueryController() { - this.provider = MonitoringHandler.getInstance().getMonitoringProvider(); + public MonitoringQueryController(MonitoringProvider provider) { + this.provider = provider; } - /** * Queries details of control loop participants statistics. * @@ -74,8 +75,8 @@ public class MonitoringQueryController extends RestController { * @return the participant statistics */ // @formatter:off - @GET - @Path("/monitoring/participant") + @GetMapping(value = "/monitoring/participant", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) @ApiOperation(value = "Query details of the requested participant stats", notes = "Queries details of the requested participant stats, returning all participant stats", response = ParticipantStatisticsList.class, @@ -112,18 +113,26 @@ public class MonitoringQueryController extends RestController { } ) // @formatter:on - public Response queryParticipantStatistics(@HeaderParam(REQUEST_ID_NAME) - @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Control Loop participant name", required = true) - @QueryParam("name") final String name, - @ApiParam(value = "Control Loop participant version", required = true) - @QueryParam("version") final String version, - @ApiParam(value = "Record count", required = false) @DefaultValue("0") - @QueryParam("recordCount") final int recordCount, - @ApiParam(value = "start time", required = false) - @QueryParam("startTime") final String startTime, - @ApiParam(value = "end time", required = false) - @QueryParam("endTime") final String endTime) { + public ResponseEntity<ParticipantStatisticsList> queryParticipantStatistics( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop participant name") @RequestParam( + value = "name", + required = false) final String name, + @ApiParam(value = "Control Loop participant version", required = false) @RequestParam( + value = "version", + required = false) final String version, + @ApiParam(value = "Record count", required = false) @RequestParam( + value = "recordCount", + required = false, + defaultValue = "0") final int recordCount, + @ApiParam(value = "start time", required = false) @RequestParam( + value = "startTime", + required = false) final String startTime, + @ApiParam(value = "end time", required = false) @RequestParam( + value = "endTime", + required = false) final String endTime) { try { Instant startTimestamp = null; @@ -135,16 +144,12 @@ public class MonitoringQueryController extends RestController { if (endTime != null) { endTimestamp = Instant.parse(endTime); } - ParticipantStatisticsList response = provider.fetchFilteredParticipantStatistics(name, version, recordCount, - startTimestamp, endTimestamp); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) - .entity(response) - .build(); + return ResponseEntity.ok().body(provider.fetchFilteredParticipantStatistics(name, version, recordCount, + startTimestamp, endTimestamp)); } catch (PfModelRuntimeException e) { LOGGER.warn("Monitoring of participants statistics failed", e); - return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), - requestId).build(); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build(); } } @@ -158,8 +163,8 @@ public class MonitoringQueryController extends RestController { * @return the control loop element statistics */ // @formatter:off - @GET - @Path("/monitoring/participants/controlloop") + @GetMapping(value = "/monitoring/participants/controlloop", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) @ApiOperation(value = "Query details of all the participant stats in a control loop", notes = "Queries details of the participant stats, returning all participant stats", response = ClElementStatisticsList.class, @@ -195,29 +200,27 @@ public class MonitoringQueryController extends RestController { } ) // @formatter:on - public Response queryParticipantStatisticsPerControlLoop(@HeaderParam(REQUEST_ID_NAME) - @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Control Loop name", required = true) - @QueryParam("name") final String name, - @ApiParam(value = "Control Loop version", required = true) - @QueryParam("version") final String version) { + public ResponseEntity<ParticipantStatisticsList> queryParticipantStatisticsPerControlLoop( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop name", required = true) @RequestParam( + value = "name", + required = false) final String name, + @ApiParam(value = "Control Loop version", required = true) @RequestParam( + value = "version", + required = false) final String version) { try { - ParticipantStatisticsList response = provider.fetchParticipantStatsPerControlLoop(name, version); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) - .entity(response) - .build(); + return ResponseEntity.ok().body(provider.fetchParticipantStatsPerControlLoop(name, version)); } catch (PfModelRuntimeException e) { LOGGER.warn("Monitoring of Cl participant statistics failed", e); - return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), - requestId).build(); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build(); } } - - /** * Queries details of all control loop element statistics per control loop. * @@ -227,8 +230,8 @@ public class MonitoringQueryController extends RestController { * @return the control loop element statistics */ // @formatter:off - @GET - @Path("/monitoring/clelements/controlloop") + @GetMapping(value = "/monitoring/clelements/controlloop", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) @ApiOperation(value = "Query details of the requested cl element stats in a control loop", notes = "Queries details of the requested cl element stats, returning all clElement stats", response = ClElementStatisticsList.class, @@ -264,30 +267,27 @@ public class MonitoringQueryController extends RestController { } ) // @formatter:on - public Response queryElementStatisticsPerControlLoop(@HeaderParam(REQUEST_ID_NAME) - @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Control Loop name", required = true) - @QueryParam("name") final String name, - @ApiParam(value = "Control Loop version", required = true) - @QueryParam("version") final String version) { + public ResponseEntity<ClElementStatisticsList> queryElementStatisticsPerControlLoop( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Control Loop name", required = true) @RequestParam( + value = "name", + required = false) final String name, + @ApiParam(value = "Control Loop version", required = true) @RequestParam( + value = "version", + required = false) final String version) { try { - ClElementStatisticsList response = provider.fetchClElementStatsPerControlLoop(name, version); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) - .entity(response) - .build(); + return ResponseEntity.ok().body(provider.fetchClElementStatsPerControlLoop(name, version)); } catch (PfModelRuntimeException e) { LOGGER.warn("Monitoring of Cl Element statistics failed", e); - return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), - requestId).build(); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build(); } } - - - /** * Queries details of all control loop element statistics per control loop. * @@ -301,8 +301,8 @@ public class MonitoringQueryController extends RestController { * @return the control loop element statistics */ // @formatter:off - @GET - @Path("/monitoring/clelement") + @GetMapping(value = "/monitoring/clelement", + produces = {MediaType.APPLICATION_JSON_VALUE, APPLICATION_YAML}) @ApiOperation(value = "Query details of the requested cl element stats", notes = "Queries details of the requested cl element stats, returning all clElement stats", response = ClElementStatisticsList.class, @@ -338,20 +338,29 @@ public class MonitoringQueryController extends RestController { } ) // @formatter:on - public Response queryElementStatistics(@HeaderParam(REQUEST_ID_NAME) - @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, - @ApiParam(value = "Participant name", required = true) - @QueryParam("name") final String name, - @ApiParam(value = "Participant version", required = true) - @QueryParam("version") final String version, - @ApiParam(value = "Record count", required = false) - @DefaultValue("0") @QueryParam("recordCount") final int recordCount, - @ApiParam(value = "Control Loop element id", required = false) - @QueryParam("id") final String id, - @ApiParam(value = "start time", required = false) - @QueryParam("startTime") final String startTime, - @ApiParam(value = "end time", required = false) - @QueryParam("endTime") final String endTime) { + public ResponseEntity<ClElementStatisticsList> queryElementStatistics( + @RequestHeader( + name = REQUEST_ID_NAME, + required = false) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId, + @ApiParam(value = "Participant name", required = true) @RequestParam( + value = "name", + required = false) final String name, + @ApiParam(value = "Participant version", required = true) @RequestParam( + value = "version", + required = false) final String version, + @ApiParam(value = "Record count", required = false) @RequestParam( + value = "recordCount", + required = false, + defaultValue = "0") final int recordCount, + @ApiParam(value = "Control Loop element id", required = false) @RequestParam( + value = "id", + required = false) final String id, + @ApiParam(value = "start time", required = false) @RequestParam( + value = "startTime", + required = false) final String startTime, + @ApiParam(value = "end time", required = false) @RequestParam( + value = "endTime", + required = false) final String endTime) { try { Instant startTimestamp = null; @@ -363,16 +372,12 @@ public class MonitoringQueryController extends RestController { if (endTime != null) { endTimestamp = Instant.parse(endTime); } - ClElementStatisticsList response = provider.fetchFilteredClElementStatistics(name, version, id, - startTimestamp, endTimestamp, recordCount); - return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId) - .entity(response) - .build(); + return ResponseEntity.ok().body(provider.fetchFilteredClElementStatistics(name, version, id, startTimestamp, + endTimestamp, recordCount)); } catch (PfModelRuntimeException | PfModelException e) { LOGGER.warn("Monitoring of Cl Element statistics failed", e); - return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())), - requestId).build(); + return ResponseEntity.status(e.getErrorResponse().getResponseCode().getStatusCode()).build(); } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java index 957f53600..323f76178 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java @@ -20,36 +20,30 @@ package org.onap.policy.clamp.controlloop.runtime.main.startstop; -import java.util.HashSet; +import java.io.Closeable; +import java.io.IOException; import java.util.List; -import java.util.Set; -import java.util.concurrent.atomic.AtomicReference; import javax.ws.rs.core.Response.Status; +import lombok.Getter; import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException; -import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler; -import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningHandler; -import org.onap.policy.clamp.controlloop.runtime.instantiation.InstantiationHandler; import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; -import org.onap.policy.clamp.controlloop.runtime.main.rest.ControlLoopAafFilter; -import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringHandler; import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; import org.onap.policy.common.endpoints.event.comm.TopicEndpointManager; import org.onap.policy.common.endpoints.event.comm.TopicSink; import org.onap.policy.common.endpoints.event.comm.TopicSource; -import org.onap.policy.common.endpoints.http.server.RestServer; import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher; -import org.onap.policy.common.parameters.ParameterService; import org.onap.policy.common.utils.services.ServiceManagerContainer; /** * This class activates the control loop runtime component as a complete service together with all its controllers, * listeners & handlers. */ -public class ClRuntimeActivator extends ServiceManagerContainer { +public class ClRuntimeActivator extends ServiceManagerContainer implements Closeable { // Name of the message type for messages on topics private static final String[] MSG_TYPE_NAMES = {"messageType"}; - private final ClRuntimeParameterGroup clRuntimeParameterGroup; + @Getter + private final ClRuntimeParameterGroup parameterGroup; // Topics from which the application receives and to which the application sends messages private List<TopicSink> topicSinks; @@ -64,15 +58,12 @@ public class ClRuntimeActivator extends ServiceManagerContainer { * Instantiate the activator for the control loop runtime as a complete service. * * @param clRuntimeParameterGroup the parameters for the control loop runtime service + * @param supervisionHandler SupervisionHandler * @throws ControlLoopRuntimeException if the activator does not start */ - public ClRuntimeActivator(final ClRuntimeParameterGroup clRuntimeParameterGroup) { - - if (clRuntimeParameterGroup == null || !clRuntimeParameterGroup.isValid()) { - throw new ControlLoopRuntimeException(Status.INTERNAL_SERVER_ERROR, "ParameterGroup not valid"); - } - - this.clRuntimeParameterGroup = clRuntimeParameterGroup; + public ClRuntimeActivator(final ClRuntimeParameterGroup clRuntimeParameterGroup, + SupervisionHandler supervisionHandler) { + this.parameterGroup = clRuntimeParameterGroup; topicSinks = TopicEndpointManager.getManager() .addTopicSinks(clRuntimeParameterGroup.getTopicParameterGroup().getTopicSinks()); @@ -87,77 +78,22 @@ public class ClRuntimeActivator extends ServiceManagerContainer { "topic message dispatcher failed to start", e); } - final AtomicReference<ControlLoopHandler> commissioningHandler = new AtomicReference<>(); - final AtomicReference<ControlLoopHandler> instantiationHandler = new AtomicReference<>(); - final AtomicReference<ControlLoopHandler> supervisionHandler = new AtomicReference<>(); - final AtomicReference<ControlLoopHandler> monitoringHandler = new AtomicReference<>(); - final AtomicReference<RestServer> restServer = new AtomicReference<>(); - // @formatter:off - addAction("Control loop runtime parameters", - () -> ParameterService.register(clRuntimeParameterGroup), - () -> ParameterService.deregister(clRuntimeParameterGroup.getName())); - addAction("Topic endpoint management", () -> TopicEndpointManager.getManager().start(), () -> TopicEndpointManager.getManager().shutdown()); - addAction("Commissioning Handler", - () -> commissioningHandler.set(new CommissioningHandler(clRuntimeParameterGroup)), - () -> commissioningHandler.get().close()); - - addAction("Instantiation Handler", - () -> instantiationHandler.set(new InstantiationHandler(clRuntimeParameterGroup)), - () -> instantiationHandler.get().close()); - - addAction("Supervision Handler", - () -> supervisionHandler.set(new SupervisionHandler(clRuntimeParameterGroup)), - () -> supervisionHandler.get().close()); - - addAction("Monitoring Handler", - () -> monitoringHandler.set(new MonitoringHandler(clRuntimeParameterGroup)), - () -> monitoringHandler.get().close()); - - addHandlerActions("Commissioning", commissioningHandler); - addHandlerActions("Instantiation", instantiationHandler); - addHandlerActions("Supervision", supervisionHandler); - addHandlerActions("Monitoring", monitoringHandler); + addAction("Supervision Providers", () -> supervisionHandler.startProviders(), + () -> supervisionHandler.stopProviders()); + addAction("Supervision Listeners", () -> supervisionHandler.startAndRegisterListeners(msgDispatcher), + () -> supervisionHandler.stopAndUnregisterListeners(msgDispatcher)); + addAction("Supervision Publishers", () -> supervisionHandler.startAndRegisterPublishers(topicSinks), + () -> supervisionHandler.stopAndUnregisterPublishers()); addAction("Topic Message Dispatcher", this::registerMsgDispatcher, this::unregisterMsgDispatcher); - - clRuntimeParameterGroup.getRestServerParameters().setName(clRuntimeParameterGroup.getName()); - - addAction("REST server", - () -> { - Set<Class<?>> providerClasses = new HashSet<>(); - providerClasses.addAll(commissioningHandler.get().getProviderClasses()); - providerClasses.addAll(instantiationHandler.get().getProviderClasses()); - providerClasses.addAll(supervisionHandler.get().getProviderClasses()); - providerClasses.addAll(monitoringHandler.get().getProviderClasses()); - - var server = new RestServer(clRuntimeParameterGroup.getRestServerParameters(), - ControlLoopAafFilter.class, - providerClasses.toArray(new Class<?>[providerClasses.size()])); - - restServer.set(server); - restServer.get().start(); - }, - () -> restServer.get().stop()); // @formatter:on } - private void addHandlerActions(final String name, final AtomicReference<ControlLoopHandler> handler) { - addAction(name + " Providers", - () -> handler.get().startProviders(), - () -> handler.get().stopProviders()); - addAction(name + " Listeners", - () -> handler.get().startAndRegisterListeners(msgDispatcher), - () -> handler.get().stopAndUnregisterListeners(msgDispatcher)); - addAction(name + " Publishers", - () -> handler.get().startAndRegisterPublishers(topicSinks), - () -> handler.get().stopAndUnregisterPublishers()); - } - /** * Registers the dispatcher with the topic source(s). */ @@ -176,12 +112,10 @@ public class ClRuntimeActivator extends ServiceManagerContainer { } } - /** - * Get the parameters used by the activator. - * - * @return the parameters of the activator - */ - public ClRuntimeParameterGroup getParameterGroup() { - return clRuntimeParameterGroup; + @Override + public void close() throws IOException { + if (isAlive()) { + stop(); + } } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeCommandLineArguments.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeCommandLineArguments.java deleted file mode 100644 index 54167e8a6..000000000 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeCommandLineArguments.java +++ /dev/null @@ -1,132 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.main.startstop; - -import java.util.Arrays; -import javax.ws.rs.core.Response; -import lombok.Getter; -import lombok.Setter; -import org.apache.commons.cli.CommandLine; -import org.apache.commons.cli.DefaultParser; -import org.apache.commons.cli.Options; -import org.apache.commons.cli.ParseException; -import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; -import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException; -import org.onap.policy.clamp.controlloop.common.startstop.CommonCommandLineArguments; -import org.onap.policy.common.utils.resources.ResourceUtils; - -/** - * This class reads and handles command line parameters for the control loop runtime service. - */ -public class ClRuntimeCommandLineArguments { - private final Options options; - private final CommonCommandLineArguments commonCommandLineArguments; - - @Getter - @Setter - private String configurationFilePath = null; - - /** - * Construct the options for the control loop runtime component. - */ - public ClRuntimeCommandLineArguments() { - options = new Options(); - commonCommandLineArguments = new CommonCommandLineArguments(options); - } - - /** - * Construct the options for the CLI editor and parse in the given arguments. - * - * @param args The command line arguments - * @throws ControlLoopRuntimeException if the arguments are invalid - */ - public ClRuntimeCommandLineArguments(final String[] args) { - // Set up the options with the default constructor - this(); - - // Parse the arguments - try { - parse(args); - } catch (final ControlLoopException e) { - throw new ControlLoopRuntimeException(Response.Status.NOT_ACCEPTABLE, - "parse error on control loop runtime parameters", e); - } - } - - /** - * Parse the command line options. - * - * @param args The command line arguments - * @return a string with a message for help and version, or null if there is no message - * @throws ControlLoopException on command argument errors - */ - public String parse(final String[] args) throws ControlLoopException { - // Clear all our arguments - setConfigurationFilePath(null); - CommandLine commandLine = null; - try { - commandLine = new DefaultParser().parse(options, args); - } catch (final ParseException e) { - throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, - "invalid command line arguments specified : " + e.getMessage()); - } - - // Arguments left over after Commons CLI does its stuff - final String[] remainingArgs = commandLine.getArgs(); - - if (remainingArgs.length > 0) { - throw new ControlLoopException(Response.Status.NOT_ACCEPTABLE, - "too many command line arguments specified : " + Arrays.toString(args)); - } - - if (commandLine.hasOption('h')) { - return commonCommandLineArguments.help(Main.class.getName(), options); - } - - if (commandLine.hasOption('v')) { - return commonCommandLineArguments.version(); - } - - if (commandLine.hasOption('c')) { - setConfigurationFilePath(commandLine.getOptionValue('c')); - } - - return null; - } - - /** - * Validate the command line options. - * - * @throws ControlLoopException on command argument validation errors - */ - public void validate() throws ControlLoopException { - commonCommandLineArguments.validate(configurationFilePath); - } - - /** - * Gets the full expanded configuration file path. - * - * @return the configuration file path - */ - public String getFullConfigurationFilePath() { - return ResourceUtils.getFilePath4Resource(getConfigurationFilePath()); - } -} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/Main.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/Main.java deleted file mode 100644 index de1ce6f5d..000000000 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/Main.java +++ /dev/null @@ -1,159 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.main.startstop; - -import java.util.Arrays; -import javax.ws.rs.core.Response; -import org.onap.policy.clamp.controlloop.common.ControlLoopConstants; -import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; -import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException; -import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; -import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterHandler; -import org.onap.policy.common.utils.resources.MessageConstants; -import org.onap.policy.common.utils.services.Registry; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * This class initiates ONAP Policy Framework Control Loop runtime component. - */ -public class Main { - - private static final Logger LOGGER = LoggerFactory.getLogger(Main.class); - - private ClRuntimeActivator activator; - private ClRuntimeParameterGroup parameterGroup; - - /** - * Instantiates the control loop runtime service. - * - * @param args the command line arguments - * @throws ControlLoopRuntimeException if the CLAMP runtime fails to start - */ - public Main(final String[] args) { - final var argumentString = Arrays.toString(args); - LOGGER.info("Starting the control loop runtime service with arguments - {}", argumentString); - - // Check the arguments - final var arguments = new ClRuntimeCommandLineArguments(); - try { - // The arguments return a string if there is a message to print and we should exit - final String argumentMessage = arguments.parse(args); - if (argumentMessage != null) { - LOGGER.info(argumentMessage); - return; - } - // Validate that the arguments are sane - arguments.validate(); - - // Read the parameters - parameterGroup = new ClRuntimeParameterHandler().getParameters(arguments); - - // Now, create the activator for the service - activator = new ClRuntimeActivator(parameterGroup); - Registry.register(ControlLoopConstants.REG_CLRUNTIME_ACTIVATOR, activator); - - // Start the activator - activator.start(); - } catch (Exception exp) { - if (null != activator) { - Registry.unregister(ControlLoopConstants.REG_CLRUNTIME_ACTIVATOR); - } - throw new ControlLoopRuntimeException(Response.Status.BAD_REQUEST, - String.format(MessageConstants.START_FAILURE_MSG, MessageConstants.POLICY_CLAMP), exp); - } - - // Add a shutdown hook to shut everything down in an orderly manner - Runtime.getRuntime().addShutdownHook(new ClRuntimeShutdownHookClass()); - var successMsg = String.format(MessageConstants.START_SUCCESS_MSG, MessageConstants.POLICY_CLAMP); - LOGGER.info(successMsg); - } - - /** - * Check if main is running. - * - * @return true if the CLAMP runtime is running - */ - public boolean isRunning() { - return activator != null && activator.isAlive(); - } - - /** - * Get the parameters specified in JSON. - * - * @return the parameters - */ - public ClRuntimeParameterGroup getParameters() { - return parameterGroup; - } - - /** - * Shut down Execution. - * - * @throws ControlLoopException on shutdown errors - */ - public void shutdown() throws ControlLoopException { - // clear the parameterGroup variable - parameterGroup = null; - - // clear the cl runtime activator - if (activator != null) { - activator.stop(); - } - } - - /** - * The Class ClRuntimeShutdownHookClass terminates the control loop runtime service when its run method is called. - */ - private class ClRuntimeShutdownHookClass extends Thread { - /* - * (non-Javadoc) - * - * @see java.lang.Runnable#run() - */ - @Override - public void run() { - if (!activator.isAlive()) { - return; - } - - try { - // Shutdown the control loop runtime service and wait for everything to stop - activator.stop(); - } catch (final RuntimeException e) { - LOGGER.warn("error occured during shut down of the control loop runtime service", e); - } - } - } - - /** - * The main method. - * - * @param args the arguments - */ - public static void main(final String[] args) { // NOSONAR - /* - * NOTE: arguments are validated by the constructor, thus sonar is disabled. - */ - - new Main(args); - } -} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/RestController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/AbstractRestController.java index 4955e4a2f..7d279ba67 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/RestController.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/AbstractRestController.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.controlloop.runtime.main.rest; +package org.onap.policy.clamp.controlloop.runtime.main.web; import io.swagger.annotations.Api; import io.swagger.annotations.BasicAuthDefinition; @@ -27,30 +27,26 @@ import io.swagger.annotations.SecurityDefinition; import io.swagger.annotations.SwaggerDefinition; import io.swagger.annotations.Tag; import java.net.HttpURLConnection; -import java.util.UUID; -import javax.ws.rs.Path; -import javax.ws.rs.Produces; import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response.ResponseBuilder; +import org.springframework.web.bind.annotation.RequestMapping; /** - * Common superclass to provide REST endpoints for the control loop service. + * Common superclass to provide REST endpoints for the participant simulator. */ // @formatter:off -@Path("/onap/controlloop/v2") -@Api(value = "Control Loop API") -@Produces({MediaType.APPLICATION_JSON, RestController.APPLICATION_YAML}) +@RequestMapping(value = "/v2", produces = {MediaType.APPLICATION_JSON, AbstractRestController.APPLICATION_YAML}) +@Api(value = "Control Loop Commissioning API") @SwaggerDefinition( - info = @Info(description = - "Control Loop Service", version = "v1.0", - title = "Control Loop"), - consumes = {MediaType.APPLICATION_JSON, RestController.APPLICATION_YAML}, - produces = {MediaType.APPLICATION_JSON, RestController.APPLICATION_YAML}, - schemes = {SwaggerDefinition.Scheme.HTTP, SwaggerDefinition.Scheme.HTTPS}, - tags = {@Tag(name = "controlloop", description = "Control Loop Service")}, - securityDefinition = @SecurityDefinition(basicAuthDefinitions = {@BasicAuthDefinition(key = "basicAuth")})) + info = @Info(description = + "Control Loop Service", version = "v1.0", + title = "Control Loop"), + consumes = {MediaType.APPLICATION_JSON, AbstractRestController.APPLICATION_YAML}, + produces = {MediaType.APPLICATION_JSON, AbstractRestController.APPLICATION_YAML}, + schemes = {SwaggerDefinition.Scheme.HTTP, SwaggerDefinition.Scheme.HTTPS}, + tags = {@Tag(name = "controlloop", description = "Control Loop Service")}, + securityDefinition = @SecurityDefinition(basicAuthDefinitions = {@BasicAuthDefinition(key = "basicAuth")})) // @formatter:on -public class RestController { +public abstract class AbstractRestController { public static final String APPLICATION_YAML = "application/yaml"; public static final String EXTENSION_NAME = "interface info"; @@ -63,12 +59,12 @@ public class RestController { public static final String VERSION_MINOR_NAME = "X-MinorVersion"; public static final String VERSION_MINOR_DESCRIPTION = - "Used to request or communicate a MINOR version back from the client" - + " to the server, and from the server back to the client"; + "Used to request or communicate a MINOR version back from the client" + + " to the server, and from the server back to the client"; public static final String VERSION_PATCH_NAME = "X-PatchVersion"; public static final String VERSION_PATCH_DESCRIPTION = "Used only to communicate a PATCH version in a response for" - + " troubleshooting purposes only, and will not be provided by" + " the client on request"; + + " troubleshooting purposes only, and will not be provided by" + " the client on request"; public static final String VERSION_LATEST_NAME = "X-LatestVersion"; public static final String VERSION_LATEST_DESCRIPTION = "Used only to communicate an API's latest version"; @@ -88,29 +84,8 @@ public class RestController { public static final String SERVER_ERROR_MESSAGE = "Internal Server Error"; /** - * Adds version headers to the response. - * - * @param respBuilder response builder - * @return the response builder, with version headers + * Constructor. */ - public ResponseBuilder addVersionControlHeaders(ResponseBuilder respBuilder) { - return respBuilder.header(VERSION_MINOR_NAME, "0").header(VERSION_PATCH_NAME, "0").header(VERSION_LATEST_NAME, - API_VERSION); - } - - /** - * Adds logging headers to the response. - * - * @param respBuilder response builder - * @param requestId unique ID for this request - * @return the response builder, with version logging - */ - public ResponseBuilder addLoggingHeaders(ResponseBuilder respBuilder, UUID requestId) { - if (requestId == null) { - // Generate a random uuid if client does not embed requestId in rest request - return respBuilder.header(REQUEST_ID_NAME, UUID.randomUUID()); - } - - return respBuilder.header(REQUEST_ID_NAME, requestId); + protected AbstractRestController() { } } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/ControlLoopAafFilter.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/ControlLoopAafFilter.java index f166de5d6..739a691c9 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/rest/ControlLoopAafFilter.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/ControlLoopAafFilter.java @@ -18,7 +18,7 @@ * ============LICENSE_END========================================================= */ -package org.onap.policy.clamp.controlloop.runtime.main.rest; +package org.onap.policy.clamp.controlloop.runtime.main.web; import org.onap.policy.common.endpoints.http.server.aaf.AafGranularAuthFilter; import org.onap.policy.common.utils.resources.MessageConstants; diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/RequestResponseLoggingFilter.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/RequestResponseLoggingFilter.java new file mode 100644 index 000000000..eb08391a9 --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/RequestResponseLoggingFilter.java @@ -0,0 +1,63 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.main.web; + +import java.io.IOException; +import java.util.UUID; +import javax.servlet.Filter; +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.springframework.core.annotation.Order; +import org.springframework.stereotype.Component; + +@Component +@Order(2) +public class RequestResponseLoggingFilter implements Filter { + + private static final String VERSION_MINOR_NAME = "X-MinorVersion"; + private static final String VERSION_PATCH_NAME = "X-PatchVersion"; + private static final String VERSION_LATEST_NAME = "X-LatestVersion"; + public static final String API_VERSION = "1.0.0"; + public static final String REQUEST_ID_NAME = "X-ONAP-RequestID"; + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) + throws IOException, ServletException { + + + HttpServletResponse res = (HttpServletResponse) response; + HttpServletRequest req = (HttpServletRequest) request; + + String requestId = req.getHeader(REQUEST_ID_NAME); + res.addHeader(REQUEST_ID_NAME, requestId != null ? requestId : UUID.randomUUID().toString()); + + res.addHeader(VERSION_MINOR_NAME, "0"); + res.addHeader(VERSION_PATCH_NAME, "0"); + res.addHeader(VERSION_LATEST_NAME, API_VERSION); + + chain.doFilter(request, response); + } + +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/RuntimeErrorController.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/RuntimeErrorController.java new file mode 100644 index 000000000..2dc7a6b8e --- /dev/null +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/web/RuntimeErrorController.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.main.web; + +import io.swagger.v3.oas.annotations.Hidden; +import java.util.Map; +import javax.servlet.RequestDispatcher; +import javax.servlet.http.HttpServletRequest; +import org.onap.policy.clamp.controlloop.models.messages.rest.SimpleResponse; +import org.onap.policy.clamp.controlloop.models.messages.rest.TypedSimpleResponse; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.web.error.ErrorAttributeOptions; +import org.springframework.boot.web.servlet.error.ErrorAttributes; +import org.springframework.boot.web.servlet.error.ErrorController; +import org.springframework.http.HttpStatus; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.context.request.ServletWebRequest; + +@Controller +@Hidden +public class RuntimeErrorController implements ErrorController { + + private static final Logger LOGGER = LoggerFactory.getLogger(RuntimeErrorController.class); + + private final ErrorAttributes errorAttributes; + + @Value("${server.error.path}") + private String path; + + /** + * Constructor. + * + * @param errorAttributes ErrorAttributes + */ + public RuntimeErrorController(ErrorAttributes errorAttributes) { + this.errorAttributes = errorAttributes; + } + + protected HttpStatus getStatus(HttpServletRequest request) { + Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE); + if (statusCode == null) { + return HttpStatus.INTERNAL_SERVER_ERROR; + } + try { + return HttpStatus.valueOf(statusCode); + } catch (Exception ex) { + LOGGER.error("statusCode {} Not Valid", statusCode, ex); + return HttpStatus.INTERNAL_SERVER_ERROR; + } + } + + /** + * Handle Errors not handled to GlobalControllerExceptionHandler. + * + * @param request HttpServletRequest + * @return ResponseEntity + */ + @RequestMapping(value = "${server.error.path}", produces = MediaType.APPLICATION_JSON_VALUE) + public ResponseEntity<TypedSimpleResponse<SimpleResponse>> handleError(HttpServletRequest request) { + Map<String, Object> map = this.errorAttributes.getErrorAttributes(new ServletWebRequest(request), + ErrorAttributeOptions.defaults()); + + StringBuilder sb = new StringBuilder(); + final Object error = map.get("error"); + if (error != null) { + sb.append(error.toString()).append(" "); + } + final Object message = map.get("message"); + if (message != null) { + sb.append(message.toString()); + } + + TypedSimpleResponse<SimpleResponse> resp = new TypedSimpleResponse<>(); + resp.setErrorDetails(sb.toString()); + + return ResponseEntity.status(getStatus(request)).body(resp); + + } +} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringHandler.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringHandler.java deleted file mode 100644 index 1584766f1..000000000 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringHandler.java +++ /dev/null @@ -1,81 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.monitoring; - -import java.io.IOException; -import java.util.Set; -import javax.ws.rs.core.Response; -import lombok.Getter; -import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler; -import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; -import org.onap.policy.clamp.controlloop.runtime.monitoring.rest.MonitoringQueryController; -import org.onap.policy.common.utils.services.Registry; -import org.onap.policy.models.base.PfModelRuntimeException; - -/** - * This class handles monitoring of control loop definitions, - * so only one object of this type should be built at a time. - * - * <p/> - * It is effectively a singleton that is started at system start. - */ -public class MonitoringHandler extends ControlLoopHandler { - - @Getter - private MonitoringProvider monitoringProvider; - - /** - * Gets the Monitoring Handler. - * - * @return MonitoringHandler - */ - public static MonitoringHandler getInstance() { - return Registry.get(MonitoringHandler.class.getName()); - } - - /** - * Create a handler. - * - * @param controlLoopParameters the parameters for access to the database - */ - public MonitoringHandler(ClRuntimeParameterGroup controlLoopParameters) { - super(controlLoopParameters.getDatabaseProviderParameters()); - } - - @Override - public Set<Class<?>> getProviderClasses() { - return Set.of(MonitoringQueryController.class); - } - - @Override - public void startProviders() { - monitoringProvider = new MonitoringProvider(getDatabaseProviderParameters()); - } - - @Override - public void stopProviders() { - try { - monitoringProvider.close(); - } catch (IOException e) { - throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR, "Cannot stop provider", e); - } - } -} diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java index 1bc1312e7..a68505877 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java @@ -36,14 +36,16 @@ import org.onap.policy.clamp.controlloop.models.controlloop.concepts.Participant import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ClElementStatisticsProvider; import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider; import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantStatisticsProvider; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; -import org.onap.policy.models.provider.PolicyModelsProviderParameters; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.springframework.stereotype.Component; /** * This class provides information about statistics data of CL elements and CL Participants in database to callers. */ +@Component public class MonitoringProvider implements Closeable { private static final String DESC_ORDER = "DESC"; @@ -54,15 +56,17 @@ public class MonitoringProvider implements Closeable { /** * Create a Monitoring provider. * - * @param parameters parameters for accessing the database for monitoring + * @param controlLoopParameters the parameters for access to the database * @throws PfModelRuntimeException on errors creating the provider */ - public MonitoringProvider(PolicyModelsProviderParameters parameters) { + public MonitoringProvider(ClRuntimeParameterGroup controlLoopParameters) { try { - participantStatisticsProvider = new ParticipantStatisticsProvider(parameters); - clElementStatisticsProvider = new ClElementStatisticsProvider(parameters); - controlLoopProvider = new ControlLoopProvider(parameters); + participantStatisticsProvider = + new ParticipantStatisticsProvider(controlLoopParameters.getDatabaseProviderParameters()); + clElementStatisticsProvider = + new ClElementStatisticsProvider(controlLoopParameters.getDatabaseProviderParameters()); + controlLoopProvider = new ControlLoopProvider(controlLoopParameters.getDatabaseProviderParameters()); } catch (PfModelException e) { throw new PfModelRuntimeException(e); } @@ -83,10 +87,10 @@ public class MonitoringProvider implements Closeable { * @throws PfModelException on creation errors */ public ParticipantStatisticsList createParticipantStatistics(List<ParticipantStatistics> participantStatistics) - throws PfModelException { + throws PfModelException { var participantStatisticsList = new ParticipantStatisticsList(); participantStatisticsList - .setStatisticsList(participantStatisticsProvider.createParticipantStatistics(participantStatistics)); + .setStatisticsList(participantStatisticsProvider.createParticipantStatistics(participantStatistics)); return participantStatisticsList; } @@ -99,10 +103,10 @@ public class MonitoringProvider implements Closeable { * @throws PfModelException on creation errors */ public ClElementStatisticsList createClElementStatistics(List<ClElementStatistics> clElementStatisticsList) - throws PfModelException { + throws PfModelException { var elementStatisticsList = new ClElementStatisticsList(); elementStatisticsList - .setClElementStatistics(clElementStatisticsProvider.createClElementStatistics(clElementStatisticsList)); + .setClElementStatistics(clElementStatisticsProvider.createClElementStatistics(clElementStatisticsList)); return elementStatisticsList; } @@ -118,13 +122,13 @@ public class MonitoringProvider implements Closeable { * @return the participant found */ public ParticipantStatisticsList fetchFilteredParticipantStatistics(@NonNull final String name, - final String version, int recordCount, Instant startTime, Instant endTime) { + final String version, int recordCount, Instant startTime, Instant endTime) { var participantStatisticsList = new ParticipantStatisticsList(); // Additional parameters can be added in filterMap for filtering data. Map<String, Object> filterMap = null; participantStatisticsList.setStatisticsList(participantStatisticsProvider.getFilteredParticipantStatistics(name, - version, startTime, endTime, filterMap, DESC_ORDER, recordCount)); + version, startTime, endTime, filterMap, DESC_ORDER, recordCount)); return participantStatisticsList; } @@ -138,16 +142,16 @@ public class MonitoringProvider implements Closeable { * @throws PfModelRuntimeException on errors getting participant statistics */ public ParticipantStatisticsList fetchParticipantStatsPerControlLoop(@NonNull final String controlLoopName, - @NonNull final String controlLoopVersion) { + @NonNull final String controlLoopVersion) { var statisticsList = new ParticipantStatisticsList(); List<ParticipantStatistics> participantStatistics = new ArrayList<>(); try { // Fetch all participantIds for a specific control loop List<ToscaConceptIdentifier> participantIds = - getAllParticipantIdsPerControlLoop(controlLoopName, controlLoopVersion); + getAllParticipantIdsPerControlLoop(controlLoopName, controlLoopVersion); for (ToscaConceptIdentifier id : participantIds) { - participantStatistics.addAll(participantStatisticsProvider - .getFilteredParticipantStatistics(id.getName(), id.getVersion(), null, null, null, DESC_ORDER, 0)); + participantStatistics.addAll(participantStatisticsProvider.getFilteredParticipantStatistics( + id.getName(), id.getVersion(), null, null, null, DESC_ORDER, 0)); } statisticsList.setStatisticsList(participantStatistics); } catch (PfModelException e) { @@ -169,7 +173,7 @@ public class MonitoringProvider implements Closeable { * @throws PfModelException on errors getting control loop statistics */ public ClElementStatisticsList fetchFilteredClElementStatistics(@NonNull final String name, final String version, - final String id, Instant startTime, Instant endTime, int recordCount) throws PfModelException { + final String id, Instant startTime, Instant endTime, int recordCount) throws PfModelException { var clElementStatisticsList = new ClElementStatisticsList(); Map<String, Object> filterMap = new HashMap<>(); // Adding UUID in filter if present @@ -177,7 +181,7 @@ public class MonitoringProvider implements Closeable { filterMap.put("localName", id); } clElementStatisticsList.setClElementStatistics(clElementStatisticsProvider.getFilteredClElementStatistics(name, - version, startTime, endTime, filterMap, DESC_ORDER, recordCount)); + version, startTime, endTime, filterMap, DESC_ORDER, recordCount)); return clElementStatisticsList; } @@ -191,7 +195,7 @@ public class MonitoringProvider implements Closeable { * @throws PfModelRuntimeException on errors getting control loop statistics */ public ClElementStatisticsList fetchClElementStatsPerControlLoop(@NonNull final String name, - @NonNull final String version) { + @NonNull final String version) { var clElementStatisticsList = new ClElementStatisticsList(); List<ClElementStatistics> clElementStats = new ArrayList<>(); try { @@ -203,8 +207,8 @@ public class MonitoringProvider implements Closeable { // Collect control loop element statistics for each cl element. for (ControlLoopElement clElement : clElements) { clElementStats.addAll(fetchFilteredClElementStatistics(clElement.getParticipantId().getName(), - clElement.getParticipantId().getVersion(), clElement.getId().toString(), null, null, 0) - .getClElementStatistics()); + clElement.getParticipantId().getVersion(), clElement.getId().toString(), null, null, 0) + .getClElementStatistics()); } } clElementStatisticsList.setClElementStatistics(clElementStats); @@ -224,7 +228,7 @@ public class MonitoringProvider implements Closeable { * @throws PfModelException on errors */ public List<ToscaConceptIdentifier> getAllParticipantIdsPerControlLoop(String name, String version) - throws PfModelException { + throws PfModelException { List<ToscaConceptIdentifier> participantIds = new ArrayList<>(); var controlLoop = controlLoopProvider.getControlLoop(new ToscaConceptIdentifier(name, version)); if (controlLoop != null) { @@ -245,7 +249,7 @@ public class MonitoringProvider implements Closeable { * @throws PfModelException on errors */ public Map<String, ToscaConceptIdentifier> getAllClElementsIdPerControlLoop(String name, String version) - throws PfModelException { + throws PfModelException { Map<String, ToscaConceptIdentifier> clElementId = new HashMap<>(); var controlLoop = controlLoopProvider.getControlLoop(new ToscaConceptIdentifier(name, version)); if (controlLoop != null) { diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java index 511185da1..e1b4be48b 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/SupervisionHandler.java @@ -38,9 +38,8 @@ import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.Parti import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantControlLoopUpdate; import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantMessageType; import org.onap.policy.clamp.controlloop.models.messages.dmaap.participant.ParticipantStatus; -import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningHandler; +import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; -import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringHandler; import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider; import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantControlLoopStateChangePublisher; import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantControlLoopUpdatePublisher; @@ -48,19 +47,20 @@ import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantSta import org.onap.policy.clamp.controlloop.runtime.supervision.comm.ParticipantStatusListener; import org.onap.policy.common.endpoints.event.comm.TopicSink; import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher; -import org.onap.policy.common.utils.services.Registry; import org.onap.policy.common.utils.services.ServiceManager; import org.onap.policy.common.utils.services.ServiceManagerException; import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; /** * This class handles supervision of control loop instances, so only one object of this type should be built at a time. * * <p/> It is effectively a singleton that is started at system start. */ +@Component public class SupervisionHandler extends ControlLoopHandler { private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionHandler.class); @@ -71,7 +71,8 @@ public class SupervisionHandler extends ControlLoopHandler { private ControlLoopProvider controlLoopProvider; private ParticipantProvider participantProvider; - private MonitoringProvider monitoringProvider; + private final MonitoringProvider monitoringProvider; + private final CommissioningProvider commissioningProvider; // Publishers for participant communication private ParticipantStateChangePublisher stateChangePublisher; @@ -93,21 +94,18 @@ public class SupervisionHandler extends ControlLoopHandler { private ServiceManager publisherManager; /** - * Gets the SupervisionHandler. - * - * @return SupervisionHandler - */ - public static SupervisionHandler getInstance() { - return Registry.get(SupervisionHandler.class.getName()); - } - - /** * Create a handler. * * @param clRuntimeParameterGroup the parameters for the control loop runtime + * @param monitoringProvider the MonitoringProvider + * @param commissioningProvider the CommissioningProvider */ - public SupervisionHandler(ClRuntimeParameterGroup clRuntimeParameterGroup) { + public SupervisionHandler(ClRuntimeParameterGroup clRuntimeParameterGroup, MonitoringProvider monitoringProvider, + CommissioningProvider commissioningProvider) { super(clRuntimeParameterGroup.getDatabaseProviderParameters()); + this.monitoringProvider = monitoringProvider; + this.commissioningProvider = commissioningProvider; + // @formatter:off this.manager = new ServiceManager() .addAction("ControlLoop Provider", @@ -128,7 +126,8 @@ public class SupervisionHandler extends ControlLoopHandler { /** * Supervision trigger called when a command is issued on control loops. * - * </p> Causes supervision to start or continue supervision on the control loops in question. + * <p/> + * Causes supervision to start or continue supervision on the control loops in question. * * @param controlLoopIdentifierList the control loops for which the supervision command has been issued * @throws ControlLoopException on supervision triggering exceptions @@ -158,7 +157,7 @@ public class SupervisionHandler extends ControlLoopHandler { @Override public void startAndRegisterListeners(MessageTypeDispatcher msgDispatcher) { - msgDispatcher.register(ParticipantMessageType.PARTICIPANT_STATUS.name(), new ParticipantStatusListener()); + msgDispatcher.register(ParticipantMessageType.PARTICIPANT_STATUS.name(), new ParticipantStatusListener(this)); } @Override @@ -250,7 +249,7 @@ public class SupervisionHandler extends ControlLoopHandler { default: exceptionOccured(Response.Status.NOT_ACCEPTABLE, - "A control loop cannot be commanded to go into state " + controlLoop.getOrderedState().name()); + "A control loop cannot be commanded to go into state " + controlLoop.getOrderedState().name()); } } @@ -346,7 +345,6 @@ public class SupervisionHandler extends ControlLoopHandler { pclu.setControlLoop(controlLoop); // TODO: We should look up the correct TOSCA node template here for the control loop // Tiny hack implemented to return the tosca service template entry from the database and be passed onto dmaap - var commissioningProvider = CommissioningHandler.getInstance().getProvider(); pclu.setControlLoopDefinition(commissioningProvider.getToscaServiceTemplate(null, null)); controlLoopUpdatePublisher.send(pclu); } @@ -388,7 +386,6 @@ public class SupervisionHandler extends ControlLoopHandler { participantProvider.updateParticipants(participantList); } - monitoringProvider = MonitoringHandler.getInstance().getMonitoringProvider(); monitoringProvider.createParticipantStatistics(List.of(participantStatusMessage.getParticipantStatistics())); } @@ -401,14 +398,14 @@ public class SupervisionHandler extends ControlLoopHandler { for (ControlLoop controlLoop : participantStatusMessage.getControlLoops().getControlLoopList()) { if (controlLoop == null) { exceptionOccured(Response.Status.NOT_FOUND, - "PARTICIPANT_STATUS message references unknown control loop: " + controlLoop); + "PARTICIPANT_STATUS message references unknown control loop: " + controlLoop); } var dbControlLoop = controlLoopProvider .getControlLoop(new ToscaConceptIdentifier(controlLoop.getName(), controlLoop.getVersion())); if (dbControlLoop == null) { exceptionOccured(Response.Status.NOT_FOUND, - "PARTICIPANT_STATUS control loop not found in database: " + controlLoop); + "PARTICIPANT_STATUS control loop not found in database: " + controlLoop); } for (ControlLoopElement element : controlLoop.getElements().values()) { @@ -425,7 +422,6 @@ public class SupervisionHandler extends ControlLoopHandler { controlLoopProvider.updateControlLoop(dbControlLoop); } - monitoringProvider = MonitoringHandler.getInstance().getMonitoringProvider(); for (ControlLoop controlLoop : participantStatusMessage.getControlLoops().getControlLoopList()) { monitoringProvider.createClElementStatistics(controlLoop.getControlLoopElementStatisticsList(controlLoop)); } diff --git a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusListener.java b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusListener.java index a05f4aa20..88b838613 100644 --- a/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusListener.java +++ b/runtime-controlloop/src/main/java/org/onap/policy/clamp/controlloop/runtime/supervision/comm/ParticipantStatusListener.java @@ -25,7 +25,6 @@ import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; import org.onap.policy.common.endpoints.event.comm.Topic.CommInfrastructure; import org.onap.policy.common.endpoints.listeners.ScoListener; import org.onap.policy.common.utils.coder.StandardCoderObject; -import org.onap.policy.common.utils.services.Registry; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -35,13 +34,14 @@ import org.slf4j.LoggerFactory; public class ParticipantStatusListener extends ScoListener<ParticipantStatus> { private static final Logger LOGGER = LoggerFactory.getLogger(ParticipantStatusListener.class); - private final SupervisionHandler supervisionHandler = Registry.get(SupervisionHandler.class.getName()); + private final SupervisionHandler supervisionHandler; /** * Constructs the object. */ - public ParticipantStatusListener() { + public ParticipantStatusListener(SupervisionHandler supervisionHandler) { super(ParticipantStatus.class); + this.supervisionHandler = supervisionHandler; } @Override diff --git a/runtime-controlloop/src/main/resources/application.yaml b/runtime-controlloop/src/main/resources/application.yaml new file mode 100644 index 000000000..af9966d40 --- /dev/null +++ b/runtime-controlloop/src/main/resources/application.yaml @@ -0,0 +1,22 @@ +spring: + security: + user: + name: healthcheck + password: zb!XztG34 + http: + converters: + preferred-json-mapper: gson + +security: + enable-csrf: false + +server: + port: 6969 + servlet: + context-path: /onap/controlloop + error: + path: /error + + +runtime: + file: src/main/resources/parameters/ClRuntimeParameters.json diff --git a/runtime-controlloop/src/test/resources/parameters/TestParametersMariaDB.json b/runtime-controlloop/src/main/resources/parameters/ClRuntimeParameters.json index 3a009f8dd..a6c19837e 100644 --- a/runtime-controlloop/src/test/resources/parameters/TestParametersMariaDB.json +++ b/runtime-controlloop/src/main/resources/parameters/ClRuntimeParameters.json @@ -27,7 +27,7 @@ "name": "PolicyProviderParameterGroup", "implementation": "org.onap.policy.models.provider.impl.DatabasePolicyModelsProviderImpl", "databaseDriver": "org.mariadb.jdbc.Driver", - "databaseUrl": "jdbc:mariadb://localhost:3306/controlloop", + "databaseUrl": "jdbc:mariadb://mariadb:3306/controlloop", "databaseUser": "policy", "databasePassword": "P01icY", "persistenceUnit": "CommissioningMariaDb" @@ -37,7 +37,7 @@ { "topic": "POLICY-CLRUNTIME-PARTICIPANT", "servers": [ - "localhost" + "message-router" ], "topicCommInfrastructure": "dmaap", "fetchTimeout": 15000 @@ -47,14 +47,14 @@ { "topic": "POLICY-CLRUNTIME-PARTICIPANT", "servers": [ - "localhost" + "message-router" ], "topicCommInfrastructure": "dmaap" }, { "topic": "POLICY-NOTIFICATION", "servers": [ - "localhost" + "message-router" ], "topicCommInfrastructure": "dmaap" } diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProviderTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProviderTest.java index 956b5e911..fdddcf996 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProviderTest.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningProviderTest.java @@ -22,26 +22,23 @@ package org.onap.policy.clamp.controlloop.runtime.commissioning; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.List; -import org.junit.Before; -import org.junit.Test; +import org.junit.jupiter.api.Test; import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.coder.YamlJsonTranslator; import org.onap.policy.common.utils.resources.ResourceUtils; -import org.onap.policy.models.provider.PolicyModelsProviderParameters; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate; import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeType; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; -public class CommissioningProviderTest { +class CommissioningProviderTest { private static final String TOSCA_SERVICE_TEMPLATE_YAML = "src/test/resources/rest/servicetemplates/pmsh_multiple_cl_tosca.yaml"; private static final String TEMPLATE_IS_NULL = ".*serviceTemplate is marked non-null but is null"; @@ -49,7 +46,6 @@ public class CommissioningProviderTest { private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator(); private static int dbNum = 0; private static final Object lockit = new Object(); - private PolicyModelsProviderParameters databaseProviderParameters; private static String getParameterGroupAsString() { dbNum++; @@ -58,15 +54,13 @@ public class CommissioningProviderTest { } /** - * Sets up db provider parameters before each test. + * return a Cl Runtime Parameters. * * @throws CoderException . */ - @Before - public void setupDbProviderParameters() throws CoderException { + public ClRuntimeParameterGroup getClRuntimeParameterGroup() throws CoderException { synchronized (lockit) { - databaseProviderParameters = CODER.decode(getParameterGroupAsString(), ClRuntimeParameterGroup.class) - .getDatabaseProviderParameters(); + return CODER.decode(getParameterGroupAsString(), ClRuntimeParameterGroup.class); } } @@ -76,14 +70,13 @@ public class CommissioningProviderTest { * @throws Exception . */ @Test - public void testGetControlLoopDefinitions() throws Exception { + void testGetControlLoopDefinitions() throws Exception { List<ToscaNodeTemplate> listOfTemplates; + ClRuntimeParameterGroup clRuntimeParameterGroup = getClRuntimeParameterGroup(); - try (CommissioningProvider provider = new CommissioningProvider(databaseProviderParameters)) { - ToscaServiceTemplate serviceTemplate = yamlTranslator - .fromYaml(ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), - ToscaServiceTemplate.class); - + try (var provider = new CommissioningProvider(clRuntimeParameterGroup)) { + ToscaServiceTemplate serviceTemplate = yamlTranslator.fromYaml( + ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), ToscaServiceTemplate.class); listOfTemplates = provider.getControlLoopDefinitions(null, null); assertThat(listOfTemplates).isEmpty(); @@ -92,16 +85,16 @@ public class CommissioningProviderTest { listOfTemplates = provider.getControlLoopDefinitions(null, null); assertThat(listOfTemplates).hasSize(2); - //Test Filtering - listOfTemplates = provider.getControlLoopDefinitions("org.onap.domain.pmsh.PMSHControlLoopDefinition", - "1.2.3"); + // Test Filtering + listOfTemplates = + provider.getControlLoopDefinitions("org.onap.domain.pmsh.PMSHControlLoopDefinition", "1.2.3"); assertThat(listOfTemplates).hasSize(1); for (ToscaNodeTemplate template : listOfTemplates) { - //Other CL elements contain PMSD instead of PMSH in their name - assertFalse(template.getName().contains("PMSD")); + // Other CL elements contain PMSD instead of PMSH in their name + assertThat(template.getName()).doesNotContain("PMSD"); } - //Test Wrong Name + // Test Wrong Name listOfTemplates = provider.getControlLoopDefinitions("WrongControlLoopName", "0.0.0"); assertThat(listOfTemplates).isEmpty(); } @@ -113,18 +106,18 @@ public class CommissioningProviderTest { * @throws Exception . */ @Test - public void testCreateControlLoopDefinitions() throws Exception { + void testCreateControlLoopDefinitions() throws Exception { List<ToscaNodeTemplate> listOfTemplates; + ClRuntimeParameterGroup clRuntimeParameterGroup = getClRuntimeParameterGroup(); - try (CommissioningProvider provider = new CommissioningProvider(databaseProviderParameters)) { - //Test Service template is null + try (var provider = new CommissioningProvider(clRuntimeParameterGroup)) { + // Test Service template is null assertThatThrownBy(() -> provider.createControlLoopDefinitions(null)).hasMessageMatching(TEMPLATE_IS_NULL); listOfTemplates = provider.getControlLoopDefinitions(null, null); assertThat(listOfTemplates).isEmpty(); - ToscaServiceTemplate serviceTemplate = yamlTranslator - .fromYaml(ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), - ToscaServiceTemplate.class); + ToscaServiceTemplate serviceTemplate = yamlTranslator.fromYaml( + ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), ToscaServiceTemplate.class); // Response should return the number of node templates present in the service template List<ToscaConceptIdentifier> affectedDefinitions = @@ -141,13 +134,13 @@ public class CommissioningProviderTest { * @throws Exception . */ @Test - public void testDeleteControlLoopDefinitions() throws Exception { + void testDeleteControlLoopDefinitions() throws Exception { List<ToscaNodeTemplate> listOfTemplates; + ClRuntimeParameterGroup clRuntimeParameterGroup = getClRuntimeParameterGroup(); - try (CommissioningProvider provider = new CommissioningProvider(databaseProviderParameters)) { - ToscaServiceTemplate serviceTemplate = yamlTranslator - .fromYaml(ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), - ToscaServiceTemplate.class); + try (var provider = new CommissioningProvider(clRuntimeParameterGroup)) { + ToscaServiceTemplate serviceTemplate = yamlTranslator.fromYaml( + ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), ToscaServiceTemplate.class); listOfTemplates = provider.getControlLoopDefinitions(null, null); assertThat(listOfTemplates).isEmpty(); @@ -168,17 +161,17 @@ public class CommissioningProviderTest { * @throws Exception . */ @Test - public void testGetControlLoopElementDefinitions() throws Exception { - try (CommissioningProvider provider = new CommissioningProvider(databaseProviderParameters)) { - ToscaServiceTemplate serviceTemplate = yamlTranslator - .fromYaml(ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), - ToscaServiceTemplate.class); + void testGetControlLoopElementDefinitions() throws Exception { + ClRuntimeParameterGroup clRuntimeParameterGroup = getClRuntimeParameterGroup(); + try (var provider = new CommissioningProvider(clRuntimeParameterGroup)) { + ToscaServiceTemplate serviceTemplate = yamlTranslator.fromYaml( + ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), ToscaServiceTemplate.class); provider.getControlLoopDefinitions(null, null); provider.createControlLoopDefinitions(serviceTemplate); - List<ToscaNodeTemplate> controlLoopDefinitionList = provider.getControlLoopDefinitions( - "org.onap.domain.pmsh.PMSHControlLoopDefinition", "1.2.3"); + List<ToscaNodeTemplate> controlLoopDefinitionList = + provider.getControlLoopDefinitions("org.onap.domain.pmsh.PMSHControlLoopDefinition", "1.2.3"); List<ToscaNodeTemplate> controlLoopElementNodeTemplates = provider.getControlLoopElementDefinitions(controlLoopDefinitionList.get(0)); diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java index f7749e164..85bb2d164 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java @@ -21,27 +21,38 @@ package org.onap.policy.clamp.controlloop.runtime.commissioning.rest; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.List; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation; import javax.ws.rs.core.Response; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.clamp.controlloop.runtime.util.rest.CommonRestController; import org.onap.policy.common.utils.coder.YamlJsonTranslator; import org.onap.policy.common.utils.resources.ResourceUtils; import org.onap.policy.models.provider.PolicyModelsProvider; import org.onap.policy.models.provider.PolicyModelsProviderFactory; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; - -public class CommissioningControllerTest extends CommonRestController { +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.web.server.LocalServerPort; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = {"classpath:application_test.properties"}) +class CommissioningControllerTest extends CommonRestController { private static final String TOSCA_SERVICE_TEMPLATE_YAML = "src/test/resources/rest/servicetemplates/pmsh_multiple_cl_tosca.yaml"; @@ -49,62 +60,67 @@ public class CommissioningControllerTest extends CommonRestController { private static final String COMMISSIONING_ENDPOINT = "commission"; private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate(); + @Autowired + private ClRuntimeParameterGroup clRuntimeParameterGroup; + + @LocalServerPort + private int randomServerPort; + /** * starts Main and inserts a commissioning template. * * @throws Exception if an error occurs */ - @BeforeClass + @BeforeAll public static void setUpBeforeClass() throws Exception { - CommonRestController.setUpBeforeClass("CommissioningApi"); serviceTemplate = yamlTranslator.fromYaml(ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML), ToscaServiceTemplate.class); } - @AfterClass - public static void teardownAfterClass() { - CommonRestController.teardownAfterClass(); + @BeforeEach + public void setUpPort() { + super.setHttpPrefix(randomServerPort); } @Test - public void testSwagger() throws Exception { + void testSwagger() throws Exception { super.testSwagger(COMMISSIONING_ENDPOINT); } @Test - public void testUnauthorizedCreate() throws Exception { + void testUnauthorizedCreate() throws Exception { assertUnauthorizedPost(COMMISSIONING_ENDPOINT, Entity.json(serviceTemplate)); } @Test - public void testUnauthorizedQuery() throws Exception { + void testUnauthorizedQuery() throws Exception { assertUnauthorizedGet(COMMISSIONING_ENDPOINT); } @Test - public void testUnauthorizedQueryElements() throws Exception { + void testUnauthorizedQueryElements() throws Exception { assertUnauthorizedGet(COMMISSIONING_ENDPOINT + "/elements"); } @Test - public void testUnauthorizedDelete() throws Exception { + void testUnauthorizedDelete() throws Exception { assertUnauthorizedDelete(COMMISSIONING_ENDPOINT); } @Test - public void testCreateBadRequest() throws Exception { + void testCreateBadRequest() throws Exception { Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); Response resp = invocationBuilder.post(Entity.json("NotToscaServiceTempalte")); - assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); + assertThat(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode()).isEqualTo(resp.getStatus()); CommissioningResponse commissioningResponse = resp.readEntity(CommissioningResponse.class); - assertNotNull(commissioningResponse.getErrorDetails()); - assertNull(commissioningResponse.getAffectedControlLoopDefinitions()); + assertThat(commissioningResponse.getErrorDetails()).isNotNull(); + assertThat(commissioningResponse.getAffectedControlLoopDefinitions()).isNull(); } @Test - public void testCreate() throws Exception { + void testCreate() throws Exception { Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); Response resp = invocationBuilder.post(Entity.json(serviceTemplate)); assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); @@ -121,7 +137,7 @@ public class CommissioningControllerTest extends CommonRestController { } @Test - public void testQuery_NoResultWithThisName() throws Exception { + void testQuery_NoResultWithThisName() throws Exception { createEntryInDB(); Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name=noResultWithThisName"); @@ -132,7 +148,7 @@ public class CommissioningControllerTest extends CommonRestController { } @Test - public void testQuery() throws Exception { + void testQuery() throws Exception { createEntryInDB(); Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); @@ -144,7 +160,7 @@ public class CommissioningControllerTest extends CommonRestController { } @Test - public void testQueryElementsBadRequest() throws Exception { + void testQueryElementsBadRequest() throws Exception { createEntryInDB(); //Call get elements with no info @@ -154,7 +170,7 @@ public class CommissioningControllerTest extends CommonRestController { } @Test - public void testQueryElements() throws Exception { + void testQueryElements() throws Exception { createEntryInDB(); Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/elements" @@ -167,17 +183,17 @@ public class CommissioningControllerTest extends CommonRestController { } @Test - public void testDeleteBadRequest() throws Exception { + void testDeleteBadRequest() throws Exception { createEntryInDB(); Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT); //Call delete with no info Response resp = invocationBuilder.delete(); - assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), resp.getStatus()); + assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); } @Test - public void testDelete() throws Exception { + void testDelete() throws Exception { createEntryInDB(); Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name=" @@ -187,7 +203,7 @@ public class CommissioningControllerTest extends CommonRestController { assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); try (PolicyModelsProvider modelsProvider = new PolicyModelsProviderFactory() - .createPolicyModelsProvider(CommonRestController.getParameters())) { + .createPolicyModelsProvider(clRuntimeParameterGroup.getDatabaseProviderParameters())) { List<ToscaServiceTemplate> templatesInDB = modelsProvider.getServiceTemplateList(null, null); assertThat(templatesInDB).isEmpty(); } @@ -195,7 +211,7 @@ public class CommissioningControllerTest extends CommonRestController { private synchronized void createEntryInDB() throws Exception { try (PolicyModelsProvider modelsProvider = new PolicyModelsProviderFactory() - .createPolicyModelsProvider(CommonRestController.getParameters())) { + .createPolicyModelsProvider(clRuntimeParameterGroup.getDatabaseProviderParameters())) { modelsProvider.createServiceTemplate(serviceTemplate); } } diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProviderTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProviderTest.java index ccc54b93f..b93bd0f0e 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProviderTest.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/ControlLoopInstantiationProviderTest.java @@ -26,9 +26,8 @@ import static org.assertj.core.api.Assertions.assertThatThrownBy; import java.io.IOException; import java.util.ArrayList; import java.util.Collections; -import org.junit.Assert; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop; @@ -36,19 +35,20 @@ import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops; import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand; import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationResponse; -import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningHandler; +import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; +import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider; import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData; import org.onap.policy.common.endpoints.event.comm.TopicSink; import org.onap.policy.models.base.PfModelException; -import org.onap.policy.models.provider.PolicyModelsProviderParameters; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; /** * Class to perform unit test of {@link ControlLoopInstantiationProvider}}. * */ -public class ControlLoopInstantiationProviderTest { +class ControlLoopInstantiationProviderTest { private static final String CL_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/controlloops/ControlLoops.json"; private static final String CL_INSTANTIATION_UPDATE_JSON = @@ -66,10 +66,10 @@ public class ControlLoopInstantiationProviderTest { private static final String ORDERED_STATE_INVALID = "ordered state invalid or not specified on command"; private static final String CONTROLLOOP_ELEMENT_NAME_NOT_FOUND = "\"ControlLoops\" INVALID, item has status INVALID\n" - + " \"entry org.onap.domain.pmsh.PMSHControlLoopDefinition\" INVALID, item has status INVALID\n" - + " \"entry org.onap.domain.pmsh.DCAEMicroservice\" INVALID, Not FOUND\n" - + " \"entry org.onap.domain.pmsh.PMSHControlLoopDefinition\" INVALID, item has status INVALID\n" - + " \"entry org.onap.domain.pmsh.DCAEMicroservice\" INVALID, Not FOUND\n"; + + " \"entry org.onap.domain.pmsh.PMSHControlLoopDefinition\" INVALID, item has status INVALID\n" + + " \"entry org.onap.domain.pmsh.DCAEMicroservice\" INVALID, Not FOUND\n" + + " \"entry org.onap.domain.pmsh.PMSHControlLoopDefinition\" INVALID, item has status INVALID\n" + + " \"entry org.onap.domain.pmsh.DCAEMicroservice\" INVALID, Not FOUND\n"; private static final String CONTROLLOOP_DEFINITION_NOT_FOUND = "\"ControlLoops\" INVALID, item has status INVALID\n" + " \"entry org.onap.domain.PMSHControlLoopDefinition\" INVALID, item has status INVALID\n" @@ -79,62 +79,61 @@ public class ControlLoopInstantiationProviderTest { + " item \"ControlLoop\" value \"org.onap.domain.PMSHControlLoopDefinition\" INVALID," + " Commissioned control loop definition not FOUND\n"; - private static PolicyModelsProviderParameters databaseProviderParameters; + private static ClRuntimeParameterGroup controlLoopParameters; private static SupervisionHandler supervisionHandler; - private static CommissioningHandler commissioningHandler; + private static CommissioningProvider commissioningProvider; /** * setup Db Provider Parameters. * * @throws PfModelException if an error occurs */ - @BeforeClass + @BeforeAll public static void setupDbProviderParameters() throws PfModelException { - databaseProviderParameters = - CommonTestData.geParameterGroup(0, "instantproviderdb").getDatabaseProviderParameters(); - commissioningHandler = new CommissioningHandler(CommonTestData.geParameterGroup(0, "instantproviderdb")); - commissioningHandler.startProviders(); - supervisionHandler = new SupervisionHandler(CommonTestData.geParameterGroup(0, "instantproviderdb")); + controlLoopParameters = CommonTestData.geParameterGroup(0, "instantproviderdb"); + commissioningProvider = new CommissioningProvider(controlLoopParameters); + var monitoringProvider = new MonitoringProvider(controlLoopParameters); + supervisionHandler = new SupervisionHandler(controlLoopParameters, monitoringProvider, commissioningProvider); supervisionHandler.startProviders(); supervisionHandler.startAndRegisterPublishers(Collections.singletonList(Mockito.mock(TopicSink.class))); } @Test - public void testInstantiationCrud() throws Exception { + void testInstantiationCrud() throws Exception { ControlLoops controlLoopsCreate = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Crud"); ControlLoops controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate); assertThat(controlLoopsDb.getControlLoopList()).isEmpty(); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(databaseProviderParameters)) { + try (ControlLoopInstantiationProvider instantiationProvider = new ControlLoopInstantiationProvider( + controlLoopParameters, commissioningProvider, supervisionHandler)) { // to validate control Loop, it needs to define ToscaServiceTemplate - InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, databaseProviderParameters); + InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, commissioningProvider); InstantiationResponse instantiationResponse = instantiationProvider.createControlLoops(controlLoopsCreate); InstantiationUtils.assertInstantiationResponse(instantiationResponse, controlLoopsCreate); controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate); assertThat(controlLoopsDb.getControlLoopList()).isNotEmpty(); - Assert.assertEquals(controlLoopsCreate, controlLoopsDb); + assertThat(controlLoopsCreate).isEqualTo(controlLoopsDb); for (ControlLoop controlLoop : controlLoopsCreate.getControlLoopList()) { ControlLoops controlLoopsGet = instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion()); assertThat(controlLoopsGet.getControlLoopList()).hasSize(1); - Assert.assertEquals(controlLoop, controlLoopsGet.getControlLoopList().get(0)); + assertThat(controlLoop).isEqualTo(controlLoopsGet.getControlLoopList().get(0)); } ControlLoops controlLoopsUpdate = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_UPDATE_JSON, "Crud"); - Assert.assertNotEquals(controlLoopsUpdate, controlLoopsDb); + assertThat(controlLoopsUpdate).isNotEqualTo(controlLoopsDb); instantiationResponse = instantiationProvider.updateControlLoops(controlLoopsUpdate); InstantiationUtils.assertInstantiationResponse(instantiationResponse, controlLoopsUpdate); controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate); assertThat(controlLoopsDb.getControlLoopList()).isNotEmpty(); - Assert.assertEquals(controlLoopsUpdate, controlLoopsDb); + assertThat(controlLoopsUpdate).isEqualTo(controlLoopsDb); InstantiationCommand instantiationCommand = InstantiationUtils.getInstantiationCommandFromResource(CL_INSTANTIATION_CHANGE_STATE_JSON, "Crud"); @@ -145,8 +144,8 @@ public class ControlLoopInstantiationProviderTest { ControlLoops controlLoopsGet = instantiationProvider.getControlLoops(toscaConceptIdentifier.getName(), toscaConceptIdentifier.getVersion()); assertThat(controlLoopsGet.getControlLoopList()).hasSize(1); - Assert.assertEquals(instantiationCommand.getOrderedState(), - controlLoopsGet.getControlLoopList().get(0).getOrderedState()); + assertThat(instantiationCommand.getOrderedState()) + .isEqualTo(controlLoopsGet.getControlLoopList().get(0).getOrderedState()); } // in order to delete a controlLoop the state must be UNINITIALISED @@ -166,8 +165,8 @@ public class ControlLoopInstantiationProviderTest { ControlLoops controlLoopsDb = new ControlLoops(); controlLoopsDb.setControlLoopList(new ArrayList<>()); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(databaseProviderParameters)) { + try (ControlLoopInstantiationProvider instantiationProvider = new ControlLoopInstantiationProvider( + controlLoopParameters, commissioningProvider, supervisionHandler)) { for (ControlLoop controlLoop : controlLoopsSource.getControlLoopList()) { ControlLoops controlLoopsFromDb = @@ -179,22 +178,22 @@ public class ControlLoopInstantiationProviderTest { } @Test - public void testInstantiationDelete() throws Exception { + void testInstantiationDelete() throws Exception { ControlLoops controlLoops = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Delete"); assertThat(getControlLoopsFromDb(controlLoops).getControlLoopList()).isEmpty(); ControlLoop controlLoop0 = controlLoops.getControlLoopList().get(0); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(databaseProviderParameters)) { + try (ControlLoopInstantiationProvider instantiationProvider = new ControlLoopInstantiationProvider( + controlLoopParameters, commissioningProvider, supervisionHandler)) { // to validate control Loop, it needs to define ToscaServiceTemplate - InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, databaseProviderParameters); + InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, commissioningProvider); assertThatThrownBy( () -> instantiationProvider.deleteControlLoop(controlLoop0.getName(), controlLoop0.getVersion())) - .hasMessageMatching(CONTROL_LOOP_NOT_FOUND); + .hasMessageMatching(CONTROL_LOOP_NOT_FOUND); InstantiationUtils.assertInstantiationResponse(instantiationProvider.createControlLoops(controlLoops), controlLoops); @@ -225,29 +224,29 @@ public class ControlLoopInstantiationProviderTest { controlLoop.setState(state); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(databaseProviderParameters)) { + try (ControlLoopInstantiationProvider instantiationProvider = new ControlLoopInstantiationProvider( + controlLoopParameters, commissioningProvider, supervisionHandler)) { instantiationProvider.updateControlLoops(controlLoops); assertThatThrownBy( () -> instantiationProvider.deleteControlLoop(controlLoop.getName(), controlLoop.getVersion())) - .hasMessageMatching(String.format(DELETE_BAD_REQUEST, state)); + .hasMessageMatching(String.format(DELETE_BAD_REQUEST, state)); } } @Test - public void testCreateControlLoops_NoDuplicates() throws Exception { + void testCreateControlLoops_NoDuplicates() throws Exception { ControlLoops controlLoopsCreate = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "NoDuplicates"); ControlLoops controlLoopsDb = getControlLoopsFromDb(controlLoopsCreate); assertThat(controlLoopsDb.getControlLoopList()).isEmpty(); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(databaseProviderParameters)) { + try (ControlLoopInstantiationProvider instantiationProvider = new ControlLoopInstantiationProvider( + controlLoopParameters, commissioningProvider, supervisionHandler)) { // to validate control Loop, it needs to define ToscaServiceTemplate - InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, databaseProviderParameters); + InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, commissioningProvider); InstantiationResponse instantiationResponse = instantiationProvider.createControlLoops(controlLoopsCreate); InstantiationUtils.assertInstantiationResponse(instantiationResponse, controlLoopsCreate); @@ -262,15 +261,15 @@ public class ControlLoopInstantiationProviderTest { } @Test - public void testCreateControlLoops_CommissionedClElementNotFound() throws Exception { + void testCreateControlLoops_CommissionedClElementNotFound() throws Exception { ControlLoops controlLoops = InstantiationUtils .getControlLoopsFromResource(CL_INSTANTIATION_DEFINITION_NAME_NOT_FOUND_JSON, "ClElementNotFound"); - try (ControlLoopInstantiationProvider provider = - new ControlLoopInstantiationProvider(databaseProviderParameters)) { + try (ControlLoopInstantiationProvider provider = new ControlLoopInstantiationProvider(controlLoopParameters, + commissioningProvider, supervisionHandler)) { // to validate control Loop, it needs to define ToscaServiceTemplate - InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, databaseProviderParameters); + InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, commissioningProvider); assertThat(getControlLoopsFromDb(controlLoops).getControlLoopList()).isEmpty(); @@ -280,41 +279,41 @@ public class ControlLoopInstantiationProviderTest { } @Test - public void testCreateControlLoops_CommissionedClNotFound() throws Exception { + void testCreateControlLoops_CommissionedClNotFound() throws Exception { ControlLoops controlLoops = InstantiationUtils .getControlLoopsFromResource(CL_INSTANTIATION_CONTROLLOOP_DEFINITION_NOT_FOUND_JSON, "ClNotFound"); assertThat(getControlLoopsFromDb(controlLoops).getControlLoopList()).isEmpty(); - try (ControlLoopInstantiationProvider provider = - new ControlLoopInstantiationProvider(databaseProviderParameters)) { + try (ControlLoopInstantiationProvider provider = new ControlLoopInstantiationProvider(controlLoopParameters, + commissioningProvider, supervisionHandler)) { assertThatThrownBy(() -> provider.createControlLoops(controlLoops)) .hasMessageMatching(CONTROLLOOP_DEFINITION_NOT_FOUND); } } @Test - public void testIssueControlLoopCommand_OrderedStateInvalid() throws ControlLoopRuntimeException, IOException { - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(databaseProviderParameters)) { + void testIssueControlLoopCommand_OrderedStateInvalid() throws ControlLoopRuntimeException, IOException { + try (ControlLoopInstantiationProvider instantiationProvider = new ControlLoopInstantiationProvider( + controlLoopParameters, commissioningProvider, supervisionHandler)) { assertThatThrownBy(() -> instantiationProvider.issueControlLoopCommand(new InstantiationCommand())) .hasMessageMatching(ORDERED_STATE_INVALID); } } @Test - public void testInstantiationVersions() throws Exception { + void testInstantiationVersions() throws Exception { // create controlLoops V1 ControlLoops controlLoopsV1 = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "V1"); assertThat(getControlLoopsFromDb(controlLoopsV1).getControlLoopList()).isEmpty(); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(databaseProviderParameters)) { + try (ControlLoopInstantiationProvider instantiationProvider = new ControlLoopInstantiationProvider( + controlLoopParameters, commissioningProvider, supervisionHandler)) { // to validate control Loop, it needs to define ToscaServiceTemplate - InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, databaseProviderParameters); + InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, commissioningProvider); InstantiationUtils.assertInstantiationResponse(instantiationProvider.createControlLoops(controlLoopsV1), controlLoopsV1); @@ -331,7 +330,7 @@ public class ControlLoopInstantiationProviderTest { ControlLoops controlLoopsGet = instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion()); assertThat(controlLoopsGet.getControlLoopList()).hasSize(1); - Assert.assertEquals(controlLoop, controlLoopsGet.getControlLoopList().get(0)); + assertThat(controlLoop).isEqualTo(controlLoopsGet.getControlLoopList().get(0)); } // DELETE controlLoops V1 @@ -351,7 +350,7 @@ public class ControlLoopInstantiationProviderTest { ControlLoops controlLoopsGet = instantiationProvider.getControlLoops(controlLoop.getName(), controlLoop.getVersion()); assertThat(controlLoopsGet.getControlLoopList()).hasSize(1); - Assert.assertEquals(controlLoop, controlLoopsGet.getControlLoopList().get(0)); + assertThat(controlLoop).isEqualTo(controlLoopsGet.getControlLoopList().get(0)); } // DELETE controlLoops V2 diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationUtils.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationUtils.java index 958d91dff..9a9fc1680 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationUtils.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationUtils.java @@ -20,25 +20,22 @@ package org.onap.policy.clamp.controlloop.runtime.instantiation; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; -import org.junit.Assert; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops; import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand; import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationResponse; +import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; import org.onap.policy.common.utils.coder.YamlJsonTranslator; import org.onap.policy.common.utils.resources.ResourceUtils; import org.onap.policy.models.base.PfModelException; -import org.onap.policy.models.provider.PolicyModelsProvider; -import org.onap.policy.models.provider.PolicyModelsProviderFactory; -import org.onap.policy.models.provider.PolicyModelsProviderParameters; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; @@ -91,9 +88,9 @@ public class InstantiationUtils { * @param controlLoops ControlLoops */ public static void assertInstantiationResponse(InstantiationResponse response, ControlLoops controlLoops) { - assertNotNull(response); - Assert.assertNull(response.getErrorDetails()); - assertEquals(response.getAffectedControlLoops().size(), controlLoops.getControlLoopList().size()); + assertThat(response).isNotNull(); + assertThat(response.getErrorDetails()).isNull(); + assertThat(response.getAffectedControlLoops().size()).isEqualTo(controlLoops.getControlLoopList().size()); for (ControlLoop controlLoop : controlLoops.getControlLoopList()) { assertTrue(response.getAffectedControlLoops().stream() .filter(ac -> ac.equals(controlLoop.getKey().asIdentifier())).findAny().isPresent()); @@ -107,7 +104,7 @@ public class InstantiationUtils { * @param command InstantiationCommand */ public static void assertInstantiationResponse(InstantiationResponse response, InstantiationCommand command) { - assertNotNull(response); + assertThat(response).isNotNull(); assertEquals(response.getAffectedControlLoops().size(), command.getControlLoopIdentifierList().size()); for (ToscaConceptIdentifier toscaConceptIdentifier : command.getControlLoopIdentifierList()) { assertTrue(response.getAffectedControlLoops().stream() @@ -122,8 +119,8 @@ public class InstantiationUtils { * @param controlLoop ControlLoop */ public static void assertInstantiationResponse(InstantiationResponse response, ControlLoop controlLoop) { - assertNotNull(response); - Assert.assertNull(response.getErrorDetails()); + assertThat(response).isNotNull(); + assertThat(response.getErrorDetails()).isNull(); assertEquals(1, response.getAffectedControlLoops().size()); assertEquals(0, response.getAffectedControlLoops().get(0).compareTo(controlLoop.getKey().asIdentifier())); } @@ -132,18 +129,15 @@ public class InstantiationUtils { * Store ToscaServiceTemplate from resource to DB. * * @param path path of the resource - * @param parameters The parameters for the implementation of the PolicyModelProvider + * @param commissioningProvider The CommissioningProvider * @throws PfModelException if an error occurs */ - public static void storeToscaServiceTemplate(String path, PolicyModelsProviderParameters parameters) + public static void storeToscaServiceTemplate(String path, CommissioningProvider commissioningProvider) throws PfModelException { ToscaServiceTemplate template = yamlTranslator.fromYaml(ResourceUtils.getResourceAsString(path), ToscaServiceTemplate.class); - try (PolicyModelsProvider modelsProvider = - new PolicyModelsProviderFactory().createPolicyModelsProvider(parameters)) { - modelsProvider.createServiceTemplate(template); - } + commissioningProvider.createControlLoopDefinitions(template); } } diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/rest/InstantiationControllerTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/rest/InstantiationControllerTest.java index 71e762455..6c9674dec 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/rest/InstantiationControllerTest.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/instantiation/rest/InstantiationControllerTest.java @@ -21,30 +21,41 @@ package org.onap.policy.clamp.controlloop.runtime.instantiation.rest; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; import javax.ws.rs.client.Entity; import javax.ws.rs.client.Invocation; import javax.ws.rs.core.Response; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoops; import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationCommand; import org.onap.policy.clamp.controlloop.models.messages.rest.instantiation.InstantiationResponse; +import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider; import org.onap.policy.clamp.controlloop.runtime.instantiation.ControlLoopInstantiationProvider; import org.onap.policy.clamp.controlloop.runtime.instantiation.InstantiationUtils; +import org.onap.policy.clamp.controlloop.runtime.main.rest.InstantiationController; import org.onap.policy.clamp.controlloop.runtime.util.rest.CommonRestController; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +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.web.server.LocalServerPort; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; /** * Class to perform unit test of {@link InstantiationController}}. * */ -public class InstantiationControllerTest extends CommonRestController { +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = {"classpath:application_test.properties"}) +class InstantiationControllerTest extends CommonRestController { private static final String CL_INSTANTIATION_CREATE_JSON = "src/test/resources/rest/controlloops/ControlLoops.json"; @@ -61,38 +72,38 @@ public class InstantiationControllerTest extends CommonRestController { private static final String INSTANTIATION_COMMAND_ENDPOINT = "instantiation/command"; + @Autowired + private ControlLoopInstantiationProvider instantiationProvider; + + @Autowired + private CommissioningProvider commissioningProvider; + + @LocalServerPort + private int randomServerPort; + /** * starts Main and inserts a commissioning template. * * @throws Exception if an error occurs */ - @BeforeClass - public static void setUpBeforeClass() throws Exception { - CommonRestController.setUpBeforeClass("InstApi"); - + @BeforeEach + public void setUpBeforeClass() throws Exception { // to validate control Loop, it needs to define ToscaServiceTemplate - InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, getParameters()); - - ControlLoops controlLoops = - InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Command"); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(getParameters())) { - instantiationProvider.createControlLoops(controlLoops); - } + InstantiationUtils.storeToscaServiceTemplate(TOSCA_TEMPLATE_YAML, commissioningProvider); } - @AfterClass - public static void teardownAfterClass() { - CommonRestController.teardownAfterClass(); + @BeforeEach + public void setUpPort() { + super.setHttpPrefix(randomServerPort); } @Test - public void testSwagger() throws Exception { + void testSwagger() throws Exception { super.testSwagger(INSTANTIATION_ENDPOINT); } @Test - public void testCreate_Unauthorized() throws Exception { + void testCreate_Unauthorized() throws Exception { ControlLoops controlLoops = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Unauthorized"); @@ -100,12 +111,12 @@ public class InstantiationControllerTest extends CommonRestController { } @Test - public void testQuery_Unauthorized() throws Exception { + void testQuery_Unauthorized() throws Exception { assertUnauthorizedGet(INSTANTIATION_ENDPOINT); } @Test - public void testUpdate_Unauthorized() throws Exception { + void testUpdate_Unauthorized() throws Exception { ControlLoops controlLoops = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_UPDATE_JSON, "Unauthorized"); @@ -113,12 +124,12 @@ public class InstantiationControllerTest extends CommonRestController { } @Test - public void testDelete_Unauthorized() throws Exception { + void testDelete_Unauthorized() throws Exception { assertUnauthorizedDelete(INSTANTIATION_ENDPOINT); } @Test - public void testCommand_Unauthorized() throws Exception { + void testCommand_Unauthorized() throws Exception { InstantiationCommand instantiationCommand = InstantiationUtils .getInstantiationCommandFromResource(CL_INSTANTIATION_CHANGE_STATE_JSON, "Unauthorized"); @@ -126,7 +137,7 @@ public class InstantiationControllerTest extends CommonRestController { } @Test - public void testCreate() throws Exception { + void testCreate() throws Exception { ControlLoops controlLoopsFromRsc = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Create"); @@ -136,21 +147,18 @@ public class InstantiationControllerTest extends CommonRestController { InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); InstantiationUtils.assertInstantiationResponse(instResponse, controlLoopsFromRsc); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(getParameters())) { - for (ControlLoop controlLoopFromRsc : controlLoopsFromRsc.getControlLoopList()) { - ControlLoops controlLoopsFromDb = instantiationProvider.getControlLoops( - controlLoopFromRsc.getKey().getName(), controlLoopFromRsc.getKey().getVersion()); + for (ControlLoop controlLoopFromRsc : controlLoopsFromRsc.getControlLoopList()) { + ControlLoops controlLoopsFromDb = instantiationProvider + .getControlLoops(controlLoopFromRsc.getKey().getName(), controlLoopFromRsc.getKey().getVersion()); - assertNotNull(controlLoopsFromDb); - assertThat(controlLoopsFromDb.getControlLoopList()).hasSize(1); - assertEquals(controlLoopFromRsc, controlLoopsFromDb.getControlLoopList().get(0)); - } + assertNotNull(controlLoopsFromDb); + assertThat(controlLoopsFromDb.getControlLoopList()).hasSize(1); + assertEquals(controlLoopFromRsc, controlLoopsFromDb.getControlLoopList().get(0)); } } @Test - public void testCreateBadRequest() throws Exception { + void testCreateBadRequest() throws Exception { ControlLoops controlLoopsFromRsc = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "CreateBadRequest"); @@ -167,7 +175,7 @@ public class InstantiationControllerTest extends CommonRestController { } @Test - public void testQuery_NoResultWithThisName() throws Exception { + void testQuery_NoResultWithThisName() throws Exception { Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT + "?name=noResultWithThisName"); Response rawresp = invocationBuilder.buildGet().invoke(); assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); @@ -176,14 +184,10 @@ public class InstantiationControllerTest extends CommonRestController { } @Test - public void testQuery() throws Exception { + void testQuery() throws Exception { // inserts a ControlLoops to DB - ControlLoops controlLoops = - InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Query"); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(getParameters())) { - instantiationProvider.createControlLoops(controlLoops); - } + var controlLoops = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Query"); + instantiationProvider.createControlLoops(controlLoops); for (ControlLoop controlLoopFromRsc : controlLoops.getControlLoopList()) { Invocation.Builder invocationBuilder = @@ -198,37 +202,32 @@ public class InstantiationControllerTest extends CommonRestController { } @Test - public void testUpdate() throws Exception { + void testUpdate() throws Exception { ControlLoops controlLoopsCreate = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Update"); - ControlLoops controlLoops = - InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_UPDATE_JSON, "Update"); - - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(getParameters())) { - instantiationProvider.createControlLoops(controlLoopsCreate); + var controlLoops = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_UPDATE_JSON, "Update"); + instantiationProvider.createControlLoops(controlLoopsCreate); - Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT); - Response resp = invocationBuilder.put(Entity.json(controlLoops)); - assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT); + Response resp = invocationBuilder.put(Entity.json(controlLoops)); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); - InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); - InstantiationUtils.assertInstantiationResponse(instResponse, controlLoops); + InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); + InstantiationUtils.assertInstantiationResponse(instResponse, controlLoops); - for (ControlLoop controlLoopUpdate : controlLoops.getControlLoopList()) { - ControlLoops controlLoopsFromDb = instantiationProvider - .getControlLoops(controlLoopUpdate.getKey().getName(), controlLoopUpdate.getKey().getVersion()); + for (ControlLoop controlLoopUpdate : controlLoops.getControlLoopList()) { + ControlLoops controlLoopsFromDb = instantiationProvider + .getControlLoops(controlLoopUpdate.getKey().getName(), controlLoopUpdate.getKey().getVersion()); - assertNotNull(controlLoopsFromDb); - assertThat(controlLoopsFromDb.getControlLoopList()).hasSize(1); - assertEquals(controlLoopUpdate, controlLoopsFromDb.getControlLoopList().get(0)); - } + assertNotNull(controlLoopsFromDb); + assertThat(controlLoopsFromDb.getControlLoopList()).hasSize(1); + assertEquals(controlLoopUpdate, controlLoopsFromDb.getControlLoopList().get(0)); } } @Test - public void testDelete_NoResultWithThisName() throws Exception { + void testDelete_NoResultWithThisName() throws Exception { Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT + "?name=noResultWithThisName"); Response resp = invocationBuilder.delete(); assertEquals(Response.Status.NOT_FOUND.getStatusCode(), resp.getStatus()); @@ -238,56 +237,51 @@ public class InstantiationControllerTest extends CommonRestController { } @Test - public void testDelete() throws Exception { + void testDelete() throws Exception { ControlLoops controlLoopsFromRsc = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Delete"); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(getParameters())) { - instantiationProvider.createControlLoops(controlLoopsFromRsc); - - for (ControlLoop controlLoopFromRsc : controlLoopsFromRsc.getControlLoopList()) { - Invocation.Builder invocationBuilder = - super.sendRequest(INSTANTIATION_ENDPOINT + "?name=" + controlLoopFromRsc.getKey().getName() - + "&version=" + controlLoopFromRsc.getKey().getVersion()); - Response resp = invocationBuilder.delete(); - assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); - InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); - InstantiationUtils.assertInstantiationResponse(instResponse, controlLoopFromRsc); - - ControlLoops controlLoopsFromDb = instantiationProvider.getControlLoops( - controlLoopFromRsc.getKey().getName(), controlLoopFromRsc.getKey().getVersion()); - assertThat(controlLoopsFromDb.getControlLoopList()).isEmpty(); - } + + instantiationProvider.createControlLoops(controlLoopsFromRsc); + + for (ControlLoop controlLoopFromRsc : controlLoopsFromRsc.getControlLoopList()) { + Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_ENDPOINT + "?name=" + + controlLoopFromRsc.getKey().getName() + "&version=" + controlLoopFromRsc.getKey().getVersion()); + Response resp = invocationBuilder.delete(); + assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus()); + InstantiationResponse instResponse = resp.readEntity(InstantiationResponse.class); + InstantiationUtils.assertInstantiationResponse(instResponse, controlLoopFromRsc); + + ControlLoops controlLoopsFromDb = instantiationProvider + .getControlLoops(controlLoopFromRsc.getKey().getName(), controlLoopFromRsc.getKey().getVersion()); + assertThat(controlLoopsFromDb.getControlLoopList()).isEmpty(); } } @Test - public void testDeleteBadRequest() throws Exception { + void testDeleteBadRequest() throws Exception { ControlLoops controlLoopsFromRsc = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "DelBadRequest"); - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(getParameters())) { - instantiationProvider.createControlLoops(controlLoopsFromRsc); - - for (ControlLoop controlLoopFromRsc : controlLoopsFromRsc.getControlLoopList()) { - Invocation.Builder invocationBuilder = - super.sendRequest(INSTANTIATION_ENDPOINT + "?name=" + controlLoopFromRsc.getKey().getName()); - Response resp = invocationBuilder.delete(); - // should be BAD_REQUEST - assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), resp.getStatus()); - } + + instantiationProvider.createControlLoops(controlLoopsFromRsc); + + for (ControlLoop controlLoopFromRsc : controlLoopsFromRsc.getControlLoopList()) { + Invocation.Builder invocationBuilder = + super.sendRequest(INSTANTIATION_ENDPOINT + "?name=" + controlLoopFromRsc.getKey().getName()); + Response resp = invocationBuilder.delete(); + // should be BAD_REQUEST + assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), resp.getStatus()); } } @Test - public void testCommand_NotFound1() throws Exception { + void testCommand_NotFound1() throws Exception { Invocation.Builder invocationBuilder = super.sendRequest(INSTANTIATION_COMMAND_ENDPOINT); Response resp = invocationBuilder.put(Entity.json(new InstantiationCommand())); assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus()); } @Test - public void testCommand_NotFound2() throws Exception { + void testCommand_NotFound2() throws Exception { InstantiationCommand command = InstantiationUtils.getInstantiationCommandFromResource(CL_INSTANTIATION_CHANGE_STATE_JSON, "Command"); command.setOrderedState(null); @@ -298,7 +292,10 @@ public class InstantiationControllerTest extends CommonRestController { } @Test - public void testCommand() throws Exception { + void testCommand() throws Exception { + var controlLoops = InstantiationUtils.getControlLoopsFromResource(CL_INSTANTIATION_CREATE_JSON, "Command"); + instantiationProvider.createControlLoops(controlLoops); + InstantiationCommand command = InstantiationUtils.getInstantiationCommandFromResource(CL_INSTANTIATION_CHANGE_STATE_JSON, "Command"); @@ -309,14 +306,11 @@ public class InstantiationControllerTest extends CommonRestController { InstantiationUtils.assertInstantiationResponse(instResponse, command); // check passive state on DB - try (ControlLoopInstantiationProvider instantiationProvider = - new ControlLoopInstantiationProvider(getParameters())) { - for (ToscaConceptIdentifier toscaConceptIdentifier : command.getControlLoopIdentifierList()) { - ControlLoops controlLoopsGet = instantiationProvider.getControlLoops(toscaConceptIdentifier.getName(), - toscaConceptIdentifier.getVersion()); - assertThat(controlLoopsGet.getControlLoopList()).hasSize(1); - assertEquals(command.getOrderedState(), controlLoopsGet.getControlLoopList().get(0).getOrderedState()); - } + for (ToscaConceptIdentifier toscaConceptIdentifier : command.getControlLoopIdentifierList()) { + ControlLoops controlLoopsGet = instantiationProvider.getControlLoops(toscaConceptIdentifier.getName(), + toscaConceptIdentifier.getVersion()); + assertThat(controlLoopsGet.getControlLoopList()).hasSize(1); + assertEquals(command.getOrderedState(), controlLoopsGet.getControlLoopList().get(0).getOrderedState()); } } } diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/rest/RestControllerTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/rest/RestControllerTest.java deleted file mode 100644 index 4f68b4f8c..000000000 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/rest/RestControllerTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.main.rest; - -import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - -import java.util.UUID; -import javax.ws.rs.Produces; -import javax.ws.rs.core.MediaType; -import javax.ws.rs.core.Response; -import org.junit.Test; - -/** - * Class to perform unit test of {@link RestController}}. - * - */ -public class RestControllerTest { - - @Test - public void testProduces() { - Produces annotation = RestController.class.getAnnotation(Produces.class); - assertNotNull(annotation); - assertThat(annotation.value()).contains(MediaType.APPLICATION_JSON) - .contains(RestController.APPLICATION_YAML); - } - - @Test - public void testAddVersionControlHeaders() { - RestController ctlr = new RestController(); - Response resp = ctlr.addVersionControlHeaders(Response.status(Response.Status.OK)).build(); - assertEquals("0", resp.getHeaderString(RestController.VERSION_MINOR_NAME)); - assertEquals("0", resp.getHeaderString(RestController.VERSION_PATCH_NAME)); - assertEquals("1.0.0", resp.getHeaderString(RestController.VERSION_LATEST_NAME)); - } - - @Test - public void testAddLoggingHeaders_Null() { - RestController ctlr = new RestController(); - Response resp = ctlr.addLoggingHeaders(Response.status(Response.Status.OK), null).build(); - assertNotNull(resp.getHeaderString(RestController.REQUEST_ID_NAME)); - } - - @Test - public void testAddLoggingHeaders_NonNull() { - UUID uuid = UUID.randomUUID(); - RestController ctlr = new RestController(); - Response resp = ctlr.addLoggingHeaders(Response.status(Response.Status.OK), uuid).build(); - assertEquals(uuid.toString(), resp.getHeaderString(RestController.REQUEST_ID_NAME)); - } - -} diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivatorTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivatorTest.java index da71c239d..7eb567259 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivatorTest.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivatorTest.java @@ -20,63 +20,46 @@ package org.onap.policy.clamp.controlloop.runtime.main.startstop; -import static org.assertj.core.api.Assertions.assertThatExceptionOfType; import static org.assertj.core.api.Assertions.assertThatIllegalStateException; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; -import org.junit.Test; -import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException; +import org.junit.jupiter.api.Test; +import org.mockito.Mockito; import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterHandler; -import org.onap.policy.common.utils.services.Registry; +import org.onap.policy.clamp.controlloop.runtime.supervision.SupervisionHandler; /** * Class to perform unit test of {@link ClRuntimeActivator}}. * */ -public class ClRuntimeActivatorTest { +class ClRuntimeActivatorTest { @Test - public void testStartAndStop() throws Exception { - Registry.newRegistry(); - final String[] configParameters = {"-c", "src/test/resources/parameters/TestParameters.json"}; - final ClRuntimeCommandLineArguments arguments = new ClRuntimeCommandLineArguments(); - arguments.parse(configParameters); - ClRuntimeParameterGroup parameterGroup = new ClRuntimeParameterHandler().getParameters(arguments); - ClRuntimeActivator activator = new ClRuntimeActivator(parameterGroup); - activator.isAlive(); + void testStartAndStop() throws Exception { + final String path = "src/test/resources/parameters/TestParameters.json"; + ClRuntimeParameterGroup parameterGroup = new ClRuntimeParameterHandler().getParameters(path); + var supervisionHandler = Mockito.mock(SupervisionHandler.class); - assertFalse(activator.isAlive()); - activator.start(); - assertTrue(activator.isAlive()); - assertTrue(activator.getParameterGroup().isValid()); - assertEquals(activator.getParameterGroup().getName(), - activator.getParameterGroup().getRestServerParameters().getName()); + try (var activator = new ClRuntimeActivator(parameterGroup, supervisionHandler)) { - // repeat start - should throw an exception - assertThatIllegalStateException().isThrownBy(() -> activator.start()); - assertTrue(activator.isAlive()); - assertTrue(activator.getParameterGroup().isValid()); + assertFalse(activator.isAlive()); + activator.start(); + assertTrue(activator.isAlive()); + assertTrue(activator.getParameterGroup().isValid()); - activator.stop(); - assertFalse(activator.isAlive()); + // repeat start - should throw an exception + assertThatIllegalStateException().isThrownBy(() -> activator.start()); + assertTrue(activator.isAlive()); + assertTrue(activator.getParameterGroup().isValid()); - // repeat stop - should throw an exception - assertThatIllegalStateException().isThrownBy(() -> activator.stop()); - assertFalse(activator.isAlive()); - } + activator.stop(); + assertFalse(activator.isAlive()); - @Test - public void testNull() { - assertThatExceptionOfType(ControlLoopRuntimeException.class).isThrownBy(() -> new ClRuntimeActivator(null)); - } - - @Test - public void testNotValid() { - ClRuntimeParameterGroup parameterGroup = new ClRuntimeParameterGroup("name"); - assertThatExceptionOfType(ControlLoopRuntimeException.class) - .isThrownBy(() -> new ClRuntimeActivator(parameterGroup)); + // repeat stop - should throw an exception + assertThatIllegalStateException().isThrownBy(() -> activator.stop()); + assertFalse(activator.isAlive()); + } } } diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/MainTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/MainTest.java deleted file mode 100644 index b06383c68..000000000 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/MainTest.java +++ /dev/null @@ -1,157 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * Copyright (C) 2021 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.onap.policy.clamp.controlloop.runtime.main.startstop; - -import static org.assertj.core.api.Assertions.assertThatCode; -import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; -import org.onap.policy.clamp.controlloop.common.ControlLoopConstants; -import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException; -import org.onap.policy.common.utils.resources.MessageConstants; -import org.onap.policy.common.utils.services.Registry; - -/** - * Class to perform unit test of {@link Main}}. - * - */ -public class MainTest { - - public static final String POLICY_CLAMP_FAILURE_MSG = - String.format(MessageConstants.START_FAILURE_MSG, MessageConstants.POLICY_CLAMP); - - /** - * Set up. - */ - @BeforeClass - public static void setUp() { - Registry.newRegistry(); - } - - /** - * Shuts "main" down. - * - * @throws Exception if an error occurs - */ - @AfterClass - public static void tearDown() throws Exception { - // shut down activator - final ClRuntimeActivator activator = - Registry.getOrDefault(ControlLoopConstants.REG_CLRUNTIME_ACTIVATOR, ClRuntimeActivator.class, null); - if (activator != null && activator.isAlive()) { - activator.shutdown(); - } - } - - @Test - public void testMain_Help() { - final String[] configParameters = {"-h"}; - Main main = new Main(configParameters); - assertFalse(main.isRunning()); - } - - @Test - public void testMain_Version() { - final String[] configParameters = {"-v"}; - Main main = new Main(configParameters); - assertFalse(main.isRunning()); - } - - @Test - public void testMain_Valid() { - final String[] configParameters = {"-c", "src/test/resources/parameters/TestParameters.json"}; - Main main = new Main(configParameters); - assertTrue(main.isRunning()); - - // ensure items were added to the registry - assertNotNull(Registry.get(ControlLoopConstants.REG_CLRUNTIME_ACTIVATOR, ClRuntimeActivator.class)); - - assertThatCode(() -> main.shutdown()).doesNotThrowAnyException(); - - assertFalse(main.isRunning()); - } - - @Test - public void testMain_NoParameter() { - assertThatConfigParameterThrownException(new String[] {}); - } - - @Test - public void testMain_FilePathNotDefined() { - assertThatConfigParameterThrownException(new String[] {"-c"}); - } - - @Test - public void testMain_TooManyCommand() { - assertThatConfigParameterThrownException(new String[] {"-h", "d"}); - } - - @Test - public void testMain_WrongParameter() { - assertThatConfigParameterThrownException(new String[] {"-d"}); - } - - private void assertThatConfigParameterThrownException(final String[] configParameters) { - assertThatThrownBy(() -> Main.main(configParameters)).isInstanceOf(ControlLoopRuntimeException.class) - .hasMessage(POLICY_CLAMP_FAILURE_MSG); - } - - @Test - public void testParticipant_NoFileWithThisName() { - assertThatConfigFileThrownException("src/test/resources/parameters/NoFileWithThisName.json"); - } - - @Test - public void testParticipant_NotValidFile() { - assertThatConfigFileThrownException("src/test/resources/parameters"); - } - - @Test - public void testParticipant_FileEmpty() { - assertThatConfigFileThrownException("src/test/resources/parameters/EmptyParameters.json"); - } - - @Test - public void testParticipant_NoParameters() { - assertThatConfigFileThrownException("src/test/resources/parameters/NoParameters.json"); - } - - @Test - public void testParticipant_InvalidParameters() { - assertThatConfigFileThrownException("src/test/resources/parameters/InvalidParameters.json"); - } - - @Test - public void testParticipant_WrongJsonFormat() { - assertThatConfigFileThrownException("src/test/resources/parameters/Unreadable.json"); - } - - private void assertThatConfigFileThrownException(final String configFilePath) { - final String[] configParameters = new String[] {"-c", configFilePath}; - assertThatThrownBy(() -> new Main(configParameters)).isInstanceOf(ControlLoopRuntimeException.class) - .hasMessage(String.format(POLICY_CLAMP_FAILURE_MSG)); - } -} diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/TestMonitoringProvider.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/TestMonitoringProvider.java index 56735ae12..580b30f9e 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/TestMonitoringProvider.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/TestMonitoringProvider.java @@ -22,7 +22,7 @@ package org.onap.policy.clamp.controlloop.runtime.monitoring; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.assertThatThrownBy; -import static org.junit.Assert.assertEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.mockito.Mockito.when; import java.io.File; @@ -32,31 +32,31 @@ import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; import org.mockito.Mockito; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatisticsList; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatisticsList; import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; import org.onap.policy.common.utils.coder.StandardCoder; -import org.onap.policy.models.provider.PolicyModelsProviderParameters; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; -public class TestMonitoringProvider { +class TestMonitoringProvider { private static final String CL_PARTICIPANT_STATISTICS_JSON = - "src/test/resources/rest/monitoring/TestParticipantStatistics.json"; + "src/test/resources/rest/monitoring/TestParticipantStatistics.json"; private static final String INVALID_PARTICIPANT_JSON_INPUT = - "src/test/resources/rest/monitoring/TestParticipantStatistics_Invalid.json"; + "src/test/resources/rest/monitoring/TestParticipantStatistics_Invalid.json"; private static final String CL_ELEMENT_STATISTICS_JSON = - "src/test/resources/rest/monitoring/TestClElementStatistics.json"; + "src/test/resources/rest/monitoring/TestClElementStatistics.json"; private static final String INVALID_CL_ELEMENT_JSON_INPUT = - "src/test/resources/rest/monitoring/TestClElementStatistics_Invalid.json"; + "src/test/resources/rest/monitoring/TestClElementStatistics_Invalid.json"; private static final Coder CODER = new StandardCoder(); private static final String CL_PROVIDER_FIELD = "controlLoopProvider"; @@ -67,21 +67,20 @@ public class TestMonitoringProvider { private static ClElementStatisticsList inputClElementStatistics; private static ClElementStatisticsList invalidClElementInput; - @BeforeClass + @BeforeAll public static void beforeSetupStatistics() throws CoderException { // Reading input json for statistics data inputParticipantStatistics = - CODER.decode(new File(CL_PARTICIPANT_STATISTICS_JSON), ParticipantStatisticsList.class); + CODER.decode(new File(CL_PARTICIPANT_STATISTICS_JSON), ParticipantStatisticsList.class); invalidParticipantInput = - CODER.decode(new File(INVALID_PARTICIPANT_JSON_INPUT), ParticipantStatisticsList.class); + CODER.decode(new File(INVALID_PARTICIPANT_JSON_INPUT), ParticipantStatisticsList.class); inputClElementStatistics = CODER.decode(new File(CL_ELEMENT_STATISTICS_JSON), ClElementStatisticsList.class); invalidClElementInput = CODER.decode(new File(INVALID_CL_ELEMENT_JSON_INPUT), ClElementStatisticsList.class); } @Test - public void testCreateParticipantStatistics() throws Exception { - PolicyModelsProviderParameters parameters = - CommonTestData.geParameterGroup(0, "createparStat").getDatabaseProviderParameters(); + void testCreateParticipantStatistics() throws Exception { + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "createparStat"); try (MonitoringProvider provider = new MonitoringProvider(parameters)) { // Creating statistics data in db with null input @@ -95,18 +94,17 @@ public class TestMonitoringProvider { // Creating statistics data from input json ParticipantStatisticsList createResponse = - provider.createParticipantStatistics(inputParticipantStatistics.getStatisticsList()); + provider.createParticipantStatistics(inputParticipantStatistics.getStatisticsList()); assertThat(createResponse.getStatisticsList()).hasSize(3); assertEquals(createResponse.getStatisticsList().toString().replaceAll("\\s+", ""), - inputParticipantStatistics.getStatisticsList().toString().replaceAll("\\s+", "")); + inputParticipantStatistics.getStatisticsList().toString().replaceAll("\\s+", "")); } } @Test - public void testGetParticipantStatistics() throws Exception { - PolicyModelsProviderParameters parameters = - CommonTestData.geParameterGroup(0, "getparStat").getDatabaseProviderParameters(); + void testGetParticipantStatistics() throws Exception { + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "getparStat"); try (MonitoringProvider provider = new MonitoringProvider(parameters)) { ParticipantStatisticsList getResponse; @@ -120,24 +118,24 @@ public class TestMonitoringProvider { getResponse = provider.fetchFilteredParticipantStatistics("name2", "1.001", 1, null, null); assertThat(getResponse.getStatisticsList()).hasSize(1); assertEquals(getResponse.getStatisticsList().get(0).toString().replaceAll("\\s+", ""), - inputParticipantStatistics.getStatisticsList().get(2).toString().replaceAll("\\s+", "")); + inputParticipantStatistics.getStatisticsList().get(2).toString().replaceAll("\\s+", "")); // Fetch statistics using timestamp getResponse = provider.fetchFilteredParticipantStatistics("name1", "1.001", 0, null, - Instant.parse("2021-01-10T15:00:00.000Z")); + Instant.parse("2021-01-10T15:00:00.000Z")); assertThat(getResponse.getStatisticsList()).hasSize(1); getResponse = provider.fetchFilteredParticipantStatistics("name1", "1.001", 0, - Instant.parse("2021-01-11T12:00:00.000Z"), Instant.parse("2021-01-11T16:00:00.000Z")); + Instant.parse("2021-01-11T12:00:00.000Z"), Instant.parse("2021-01-11T16:00:00.000Z")); assertThat(getResponse.getStatisticsList()).isEmpty(); } } @Test - public void testCreateClElementStatistics() throws Exception { - PolicyModelsProviderParameters parameters = - CommonTestData.geParameterGroup(0, "createelemstat").getDatabaseProviderParameters(); + void testCreateClElementStatistics() throws Exception { + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "createelemstat"); + try (MonitoringProvider provider = new MonitoringProvider(parameters)) { // Creating statistics data in db with null input assertThatThrownBy(() -> { @@ -150,18 +148,18 @@ public class TestMonitoringProvider { // Creating clElement statistics data from input json ClElementStatisticsList createResponse = - provider.createClElementStatistics(inputClElementStatistics.getClElementStatistics()); + provider.createClElementStatistics(inputClElementStatistics.getClElementStatistics()); assertThat(createResponse.getClElementStatistics()).hasSize(4); assertEquals(createResponse.getClElementStatistics().toString().replaceAll("\\s+", ""), - inputClElementStatistics.getClElementStatistics().toString().replaceAll("\\s+", "")); + inputClElementStatistics.getClElementStatistics().toString().replaceAll("\\s+", "")); } } @Test - public void testGetClElementStatistics() throws Exception { - PolicyModelsProviderParameters parameters = - CommonTestData.geParameterGroup(0, "getelemstat").getDatabaseProviderParameters(); + void testGetClElementStatistics() throws Exception { + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "getelemstat"); + try (MonitoringProvider provider = new MonitoringProvider(parameters)) { ClElementStatisticsList getResponse; @@ -175,24 +173,24 @@ public class TestMonitoringProvider { assertThat(getResponse.getClElementStatistics()).hasSize(2); assertEquals(getResponse.getClElementStatistics().get(0).toString().replaceAll("\\s+", ""), - inputClElementStatistics.getClElementStatistics().get(0).toString().replaceAll("\\s+", "")); + inputClElementStatistics.getClElementStatistics().get(0).toString().replaceAll("\\s+", "")); // Fetch specific statistics record with name, id and record count getResponse = provider.fetchFilteredClElementStatistics("name1", "1.001", - "709c62b3-8918-41b9-a747-d21eb79c6c20", null, null, 0); + "709c62b3-8918-41b9-a747-d21eb79c6c20", null, null, 0); assertThat(getResponse.getClElementStatistics()).hasSize(2); // Fetch statistics using timestamp getResponse = provider.fetchFilteredClElementStatistics("name1", "1.001", null, - Instant.parse("2021-01-10T13:45:00.000Z"), null, 0); + Instant.parse("2021-01-10T13:45:00.000Z"), null, 0); assertThat(getResponse.getClElementStatistics()).hasSize(2); } } @Test - public void testGetParticipantStatsPerCL() throws Exception { - PolicyModelsProviderParameters parameters = - CommonTestData.geParameterGroup(0, "getparStatCL").getDatabaseProviderParameters(); + void testGetParticipantStatsPerCL() throws Exception { + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "getparStatCL"); + try (MonitoringProvider provider = Mockito.spy(new MonitoringProvider(parameters))) { provider.createParticipantStatistics(inputParticipantStatistics.getStatisticsList()); @@ -204,23 +202,23 @@ public class TestMonitoringProvider { getResponse = provider.fetchParticipantStatsPerControlLoop("testName", "1.001"); assertThat(getResponse.getStatisticsList()).hasSize(2); assertEquals(getResponse.getStatisticsList().get(0).toString().replaceAll("\\s+", ""), - inputParticipantStatistics.getStatisticsList().get(0).toString().replaceAll("\\s+", "")); + inputParticipantStatistics.getStatisticsList().get(0).toString().replaceAll("\\s+", "")); assertThat(provider.fetchParticipantStatsPerControlLoop("invalidCLName", "1.002").getStatisticsList()) - .isEmpty(); + .isEmpty(); } } @Test - public void testClElementStatsPerCL() throws Exception { - PolicyModelsProviderParameters parameters = - CommonTestData.geParameterGroup(0, "getelemstatPerCL").getDatabaseProviderParameters(); + void testClElementStatsPerCL() throws Exception { + ClRuntimeParameterGroup parameters = CommonTestData.geParameterGroup(0, "getelemstatPerCL"); + // Setup a dummy Control loop data ControlLoopElement mockClElement = new ControlLoopElement(); mockClElement.setId(inputClElementStatistics.getClElementStatistics().get(0).getId()); mockClElement.setParticipantId(new ToscaConceptIdentifier( - inputClElementStatistics.getClElementStatistics().get(0).getParticipantId().getName(), - inputClElementStatistics.getClElementStatistics().get(0).getParticipantId().getVersion())); + inputClElementStatistics.getClElementStatistics().get(0).getParticipantId().getName(), + inputClElementStatistics.getClElementStatistics().get(0).getParticipantId().getVersion())); ControlLoop mockCL = new ControlLoop(); mockCL.setElements(new LinkedHashMap<>()); mockCL.getElements().put(mockClElement.getId(), mockClElement); @@ -240,16 +238,15 @@ public class TestMonitoringProvider { assertThat(getResponse.getClElementStatistics()).hasSize(2); assertEquals(getResponse.getClElementStatistics().get(1).toString().replaceAll("\\s+", ""), - inputClElementStatistics.getClElementStatistics().get(1).toString().replaceAll("\\s+", "")); + inputClElementStatistics.getClElementStatistics().get(1).toString().replaceAll("\\s+", "")); - assertThat( - monitoringProvider.fetchClElementStatsPerControlLoop("invalidCLName", "1.002").getClElementStatistics()) - .isEmpty(); + assertThat(monitoringProvider.fetchClElementStatsPerControlLoop("invalidCLName", "1.002") + .getClElementStatistics()).isEmpty(); Map<String, ToscaConceptIdentifier> clElementIds = - monitoringProvider.getAllClElementsIdPerControlLoop("testCLName", "1.001"); + monitoringProvider.getAllClElementsIdPerControlLoop("testCLName", "1.001"); assertThat(clElementIds) - .containsKey(inputClElementStatistics.getClElementStatistics().get(0).getId().toString()); + .containsKey(inputClElementStatistics.getClElementStatistics().get(0).getId().toString()); } } } diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryControllerTest.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryControllerTest.java index a846d9317..95b2113cd 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryControllerTest.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryControllerTest.java @@ -21,29 +21,40 @@ package org.onap.policy.clamp.controlloop.runtime.monitoring.rest; import static org.assertj.core.api.Assertions.assertThat; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; import java.io.File; import java.time.Instant; import javax.ws.rs.client.Invocation; import javax.ws.rs.core.Response; -import org.junit.AfterClass; -import org.junit.BeforeClass; -import org.junit.Test; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatisticsList; import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatisticsList; +import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup; import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider; import org.onap.policy.clamp.controlloop.runtime.util.rest.CommonRestController; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.StandardCoder; - -public class MonitoringQueryControllerTest extends CommonRestController { +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.web.server.LocalServerPort; +import org.springframework.test.context.TestPropertySource; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@TestPropertySource(locations = {"classpath:application_test.properties"}) +class MonitoringQueryControllerTest extends CommonRestController { private static final String CL_PARTICIPANT_STATISTICS_JSON = - "src/test/resources/rest/monitoring/TestParticipantStatistics.json"; + "src/test/resources/rest/monitoring/TestParticipantStatistics.json"; private static final String CL_ELEMENT_STATISTICS_JSON = - "src/test/resources/rest/monitoring/TestClElementStatistics.json"; + "src/test/resources/rest/monitoring/TestClElementStatistics.json"; private static final Coder CODER = new StandardCoder(); @@ -51,64 +62,68 @@ public class MonitoringQueryControllerTest extends CommonRestController { private static ClElementStatisticsList inputClElementStatistics; private static ParticipantStatisticsList participantStatisticsList; - private static ClElementStatisticsList clElementStatisticsList; + private static ClElementStatisticsList clElementStatisticsList; private static final String CLELEMENT_STATS_ENDPOINT = "monitoring/clelement"; private static final String PARTICIPANT_STATS_ENDPOINT = "monitoring/participant"; private static final String PARTICIPANT_STATS_PER_CL_ENDPOINT = "monitoring/participants/controlloop"; private static final String CLELEMENT_STATS_PER_CL_ENDPOINT = "monitoring/clelements/controlloop"; + @Autowired + private ClRuntimeParameterGroup clRuntimeParameterGroup; + + @LocalServerPort + private int randomServerPort; /** * starts Main. * * @throws Exception if an error occurs */ - @BeforeClass - public static void setUpBeforeClass() throws Exception { - CommonRestController.setUpBeforeClass("testStatisticsQuery"); - inputParticipantStatistics = CODER.decode(new File(CL_PARTICIPANT_STATISTICS_JSON), - ParticipantStatisticsList.class); - inputClElementStatistics = CODER.decode(new File(CL_ELEMENT_STATISTICS_JSON), - ClElementStatisticsList.class); - - try (MonitoringProvider monitoringProvider = new MonitoringProvider(getParameters())) { + @BeforeAll + public static void setUpBeforeAll() throws Exception { + + inputParticipantStatistics = + CODER.decode(new File(CL_PARTICIPANT_STATISTICS_JSON), ParticipantStatisticsList.class); + inputClElementStatistics = CODER.decode(new File(CL_ELEMENT_STATISTICS_JSON), ClElementStatisticsList.class); + } + + @BeforeEach + public void setUpBeforeEach() throws Exception { + super.setHttpPrefix(randomServerPort); + + try (var monitoringProvider = new MonitoringProvider(clRuntimeParameterGroup)) { // Insert Participant statistics to DB - participantStatisticsList = monitoringProvider.createParticipantStatistics(inputParticipantStatistics - .getStatisticsList()); + participantStatisticsList = + monitoringProvider.createParticipantStatistics(inputParticipantStatistics.getStatisticsList()); // Insert CL Element statistics to DB - clElementStatisticsList = monitoringProvider.createClElementStatistics(inputClElementStatistics - .getClElementStatistics()); + clElementStatisticsList = + monitoringProvider.createClElementStatistics(inputClElementStatistics.getClElementStatistics()); } } - @AfterClass - public static void teardownAfterClass() { - CommonRestController.teardownAfterClass(); - } - @Test - public void testQuery_Unauthorized_for_ClElementStats() throws Exception { + void testQuery_Unauthorized_for_ClElementStats() throws Exception { assertUnauthorizedGet(CLELEMENT_STATS_ENDPOINT); } @Test - public void testQuery_Unauthorized_for_ClParticipantStats() throws Exception { + void testQuery_Unauthorized_for_ClParticipantStats() throws Exception { assertUnauthorizedGet(PARTICIPANT_STATS_ENDPOINT); } @Test - public void testQuery_Unauthorized_for_ParticipantStatsPerCl() throws Exception { + void testQuery_Unauthorized_for_ParticipantStatsPerCl() throws Exception { assertUnauthorizedGet(PARTICIPANT_STATS_PER_CL_ENDPOINT); } @Test - public void testQuery_Unauthorized_for_ClElementStatsPerCl() throws Exception { + void testQuery_Unauthorized_for_ClElementStatsPerCl() throws Exception { assertUnauthorizedGet(CLELEMENT_STATS_PER_CL_ENDPOINT); } @Test - public void testSwagger_ClStats() throws Exception { + void testSwagger_ClStats() throws Exception { super.testSwagger(CLELEMENT_STATS_ENDPOINT); super.testSwagger(PARTICIPANT_STATS_ENDPOINT); super.testSwagger(CLELEMENT_STATS_PER_CL_ENDPOINT); @@ -116,13 +131,12 @@ public class MonitoringQueryControllerTest extends CommonRestController { } @Test - public void testClElementStatisticsEndpoint() throws Exception { + void testClElementStatisticsEndpoint() throws Exception { // Filter statistics only based on participant Id and UUID - Invocation.Builder invokeRequest1 = - super.sendRequest(CLELEMENT_STATS_ENDPOINT + "?name=" + clElementStatisticsList - .getClElementStatistics().get(0).getParticipantId().getName() + "&version=" + clElementStatisticsList - .getClElementStatistics().get(0).getParticipantId().getVersion() + "&id=" + clElementStatisticsList - .getClElementStatistics().get(0).getId().toString()); + Invocation.Builder invokeRequest1 = super.sendRequest(CLELEMENT_STATS_ENDPOINT + "?name=" + + clElementStatisticsList.getClElementStatistics().get(0).getParticipantId().getName() + "&version=" + + clElementStatisticsList.getClElementStatistics().get(0).getParticipantId().getVersion() + "&id=" + + clElementStatisticsList.getClElementStatistics().get(0).getId().toString()); Response response1 = invokeRequest1.buildGet().invoke(); assertEquals(Response.Status.OK.getStatusCode(), response1.getStatus()); @@ -130,55 +144,49 @@ public class MonitoringQueryControllerTest extends CommonRestController { assertNotNull(result1); assertThat(result1.getClElementStatistics()).hasSize(2); - assertEquals(result1.getClElementStatistics().get(0), clElementStatisticsList - .getClElementStatistics().get(0)); + assertEquals(result1.getClElementStatistics().get(0), clElementStatisticsList.getClElementStatistics().get(0)); // Filter statistics based on timestamp - Invocation.Builder invokeRequest2 = - super.sendRequest(CLELEMENT_STATS_ENDPOINT + "?name=" + clElementStatisticsList - .getClElementStatistics().get(1).getParticipantId().getName() + "&version=" + clElementStatisticsList - .getClElementStatistics().get(1).getParticipantId().getVersion() + "&startTime=" - + Instant.parse("2021-01-10T13:00:00.000Z") + "&endTime=" + Instant.parse("2021-01-10T14:00:00.000Z")); + Invocation.Builder invokeRequest2 = super.sendRequest(CLELEMENT_STATS_ENDPOINT + "?name=" + + clElementStatisticsList.getClElementStatistics().get(1).getParticipantId().getName() + "&version=" + + clElementStatisticsList.getClElementStatistics().get(1).getParticipantId().getVersion() + + "&startTime=" + Instant.parse("2021-01-10T13:00:00.000Z") + "&endTime=" + + Instant.parse("2021-01-10T14:00:00.000Z")); Response response2 = invokeRequest2.buildGet().invoke(); assertEquals(Response.Status.OK.getStatusCode(), response2.getStatus()); ClElementStatisticsList result2 = response2.readEntity(ClElementStatisticsList.class); assertNotNull(result2); assertThat(result2.getClElementStatistics()).hasSize(1); - assertEquals(result1.getClElementStatistics().get(0), clElementStatisticsList - .getClElementStatistics().get(0)); + assertEquals(result1.getClElementStatistics().get(0), clElementStatisticsList.getClElementStatistics().get(0)); } @Test - public void testClElementStats_BadRequest() throws Exception { - Invocation.Builder invokeRequest1 = - super.sendRequest(CLELEMENT_STATS_ENDPOINT + "?version=1.0.0"); + void testClElementStats_BadRequest() throws Exception { + Invocation.Builder invokeRequest1 = super.sendRequest(CLELEMENT_STATS_ENDPOINT + "?version=1.0.0"); Response response1 = invokeRequest1.buildGet().invoke(); assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response1.getStatus()); } @Test - public void testParticipantStatisticsEndpoint() throws Exception { + void testParticipantStatisticsEndpoint() throws Exception { // Filter statistics only based on participant Id - Invocation.Builder invokeRequest1 = - super.sendRequest(PARTICIPANT_STATS_ENDPOINT + "?name=" + participantStatisticsList - .getStatisticsList().get(0).getParticipantId().getName() + "&version=" + participantStatisticsList - .getStatisticsList().get(0).getParticipantId().getVersion()); + Invocation.Builder invokeRequest1 = super.sendRequest(PARTICIPANT_STATS_ENDPOINT + "?name=" + + participantStatisticsList.getStatisticsList().get(0).getParticipantId().getName() + "&version=" + + participantStatisticsList.getStatisticsList().get(0).getParticipantId().getVersion()); Response response1 = invokeRequest1.buildGet().invoke(); assertEquals(Response.Status.OK.getStatusCode(), response1.getStatus()); ParticipantStatisticsList result1 = response1.readEntity(ParticipantStatisticsList.class); assertNotNull(result1); assertThat(result1.getStatisticsList()).hasSize(2); - assertEquals(result1.getStatisticsList().get(0), participantStatisticsList - .getStatisticsList().get(0)); + assertEquals(result1.getStatisticsList().get(0), participantStatisticsList.getStatisticsList().get(0)); // Filter statistics based on timestamp - Invocation.Builder invokeRequest2 = - super.sendRequest(PARTICIPANT_STATS_ENDPOINT + "?name=" + participantStatisticsList - .getStatisticsList().get(1).getParticipantId().getName() + "&version=" + participantStatisticsList - .getStatisticsList().get(1).getParticipantId().getVersion() + "&startTime=" + Invocation.Builder invokeRequest2 = super.sendRequest(PARTICIPANT_STATS_ENDPOINT + "?name=" + + participantStatisticsList.getStatisticsList().get(1).getParticipantId().getName() + "&version=" + + participantStatisticsList.getStatisticsList().get(1).getParticipantId().getVersion() + "&startTime=" + Instant.parse("2021-01-10T13:00:00.000Z") + "&endTime=" + Instant.parse("2021-01-10T14:00:00.000Z")); Response response2 = invokeRequest2.buildGet().invoke(); assertEquals(Response.Status.OK.getStatusCode(), response2.getStatus()); @@ -186,22 +194,20 @@ public class MonitoringQueryControllerTest extends CommonRestController { assertNotNull(result2); assertThat(result2.getStatisticsList()).hasSize(1); - assertEquals(result1.getStatisticsList().get(0), participantStatisticsList - .getStatisticsList().get(0)); + assertEquals(result1.getStatisticsList().get(0), participantStatisticsList.getStatisticsList().get(0)); } @Test - public void testParticipantStats_BadRequest() throws Exception { - Invocation.Builder invokeRequest1 = - super.sendRequest(PARTICIPANT_STATS_ENDPOINT + "?version=0.0"); + void testParticipantStats_BadRequest() throws Exception { + Invocation.Builder invokeRequest1 = super.sendRequest(PARTICIPANT_STATS_ENDPOINT + "?version=0.0"); Response response1 = invokeRequest1.buildGet().invoke(); assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response1.getStatus()); } @Test - public void testParticipantStatsPerClEndpoint() throws Exception { + void testParticipantStatsPerClEndpoint() throws Exception { Invocation.Builder invokeRequest1 = - super.sendRequest(PARTICIPANT_STATS_PER_CL_ENDPOINT + "?name=dummyName&version=1.001"); + super.sendRequest(PARTICIPANT_STATS_PER_CL_ENDPOINT + "?name=dummyName&version=1.001"); Response response1 = invokeRequest1.buildGet().invoke(); assertEquals(Response.Status.OK.getStatusCode(), response1.getStatus()); ParticipantStatisticsList result1 = response1.readEntity(ParticipantStatisticsList.class); @@ -209,17 +215,16 @@ public class MonitoringQueryControllerTest extends CommonRestController { } @Test - public void testParticipantStatsPerCl_BadRequest() throws Exception { - Invocation.Builder invokeRequest1 = - super.sendRequest(PARTICIPANT_STATS_PER_CL_ENDPOINT); + void testParticipantStatsPerCl_BadRequest() throws Exception { + Invocation.Builder invokeRequest1 = super.sendRequest(PARTICIPANT_STATS_PER_CL_ENDPOINT); Response response1 = invokeRequest1.buildGet().invoke(); assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response1.getStatus()); } @Test - public void testClElementStatisticsPerClEndpoint() throws Exception { + void testClElementStatisticsPerClEndpoint() throws Exception { Invocation.Builder invokeRequest1 = - super.sendRequest(CLELEMENT_STATS_PER_CL_ENDPOINT + "?name=dummyName&version=1.001"); + super.sendRequest(CLELEMENT_STATS_PER_CL_ENDPOINT + "?name=dummyName&version=1.001"); Response response1 = invokeRequest1.buildGet().invoke(); assertEquals(Response.Status.OK.getStatusCode(), response1.getStatus()); ClElementStatisticsList result1 = response1.readEntity(ClElementStatisticsList.class); @@ -227,9 +232,8 @@ public class MonitoringQueryControllerTest extends CommonRestController { } @Test - public void testClElementStatsPerCl_BadRequest() throws Exception { - Invocation.Builder invokeRequest1 = - super.sendRequest(CLELEMENT_STATS_PER_CL_ENDPOINT); + void testClElementStatsPerCl_BadRequest() throws Exception { + Invocation.Builder invokeRequest1 = super.sendRequest(CLELEMENT_STATS_PER_CL_ENDPOINT); Response response1 = invokeRequest1.buildGet().invoke(); assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), response1.getStatus()); } diff --git a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/util/rest/CommonRestController.java b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/util/rest/CommonRestController.java index 00b9c6715..eebaa5281 100644 --- a/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/util/rest/CommonRestController.java +++ b/runtime-controlloop/src/test/java/org/onap/policy/clamp/controlloop/runtime/util/rest/CommonRestController.java @@ -20,14 +20,9 @@ package org.onap.policy.clamp.controlloop.runtime.util.rest; +import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import java.io.File; -import java.io.FileNotFoundException; -import java.io.FileOutputStream; -import java.io.IOException; -import java.nio.charset.StandardCharsets; import javax.ws.rs.client.Client; import javax.ws.rs.client.ClientBuilder; import javax.ws.rs.client.Entity; @@ -37,15 +32,8 @@ import javax.ws.rs.core.MediaType; import javax.ws.rs.core.Response; import org.glassfish.jersey.client.ClientProperties; import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; -import org.onap.policy.clamp.controlloop.common.exception.ControlLoopException; -import org.onap.policy.clamp.controlloop.runtime.main.startstop.Main; -import org.onap.policy.clamp.controlloop.runtime.util.CommonTestData; import org.onap.policy.common.gson.GsonMessageBodyHandler; import org.onap.policy.common.utils.network.NetworkUtil; -import org.onap.policy.common.utils.services.Registry; -import org.onap.policy.models.provider.PolicyModelsProviderParameters; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Class to perform Rest unit tests. @@ -53,46 +41,10 @@ import org.slf4j.LoggerFactory; */ public class CommonRestController { - private static final String CONFIG_FILE = "src/test/resources/parameters/RuntimeConfigParameters%d.json"; - - private static final Logger LOGGER = LoggerFactory.getLogger(CommonRestController.class); - public static final String SELF = NetworkUtil.getHostname(); public static final String ENDPOINT_PREFIX = "onap/controlloop/v2/"; - private static int port; private static String httpPrefix; - private static Main main; - - /** - * Allocates a port for the server, writes a config file, and then starts Main. - * - * @param dbName database name - * @throws Exception if an error occurs - */ - public static void setUpBeforeClass(final String dbName) throws Exception { - port = NetworkUtil.allocPort(); - - httpPrefix = "http://" + SELF + ":" + port + "/"; - - makeConfigFile(dbName); - startMain(); - } - - /** - * Stops Main. - */ - public static void teardownAfterClass() { - try { - stopMain(); - } catch (Exception ex) { - LOGGER.error("cannot stop main", ex); - } - } - - protected static PolicyModelsProviderParameters getParameters() { - return main.getParameters().getDatabaseProviderParameters(); - } /** * Verifies that an endpoint appears within the swagger response. @@ -101,71 +53,10 @@ public class CommonRestController { * @throws Exception if an error occurs */ protected void testSwagger(final String endpoint) throws Exception { - final Invocation.Builder invocationBuilder = sendFqeRequest(httpPrefix + "swagger.yaml", true); + final Invocation.Builder invocationBuilder = sendRequest("api-docs"); final String resp = invocationBuilder.get(String.class); - assertTrue(resp.contains(ENDPOINT_PREFIX + endpoint + ":")); - } - - /** - * Makes a parameter configuration file. - * - * @param dbName database name - * @throws IOException if an error occurs writing the configuration file - * @throws FileNotFoundException if an error occurs writing the configuration file - */ - private static void makeConfigFile(final String dbName) throws FileNotFoundException, IOException { - String json = CommonTestData.getParameterGroupAsString(port, dbName); - - File file = new File(String.format(CONFIG_FILE, port)); - file.deleteOnExit(); - - try (FileOutputStream output = new FileOutputStream(file)) { - output.write(json.getBytes(StandardCharsets.UTF_8)); - } - } - - /** - * Starts the "Main". - * - * @throws InterruptedException if the NetworkUtil method calls are interrupted - * @throws IllegalStateException if a controller cannot be started on the requested port - */ - protected static void startMain() throws InterruptedException { - Registry.newRegistry(); - - // make sure port is available - if (NetworkUtil.isTcpPortOpen(SELF, port, 1, 1L)) { - throw new IllegalStateException("port " + port + " is not available"); - } - - final String[] configParameters = {"-c", String.format(CONFIG_FILE, port)}; - - main = new Main(configParameters); - - if (!NetworkUtil.isTcpPortOpen(SELF, port, 40, 250L)) { - throw new IllegalStateException("server is not listening on port " + port); - } - } - - /** - * Stops the "Main". - * - * @throws ControlLoopException if an error occurs shutting down the controller - * @throws InterruptedException if the NetworkUtil method calls are interrupted - * @throws IllegalStateException if a controller cannot be started on the requested port - */ - private static void stopMain() throws ControlLoopException, InterruptedException { - if (main != null) { - Main main2 = main; - main = null; - - main2.shutdown(); - } - // make sure port is close - if (NetworkUtil.isTcpPortOpen(SELF, port, 1, 1L)) { - throw new IllegalStateException("port " + port + " is still in use"); - } + assertThat(resp).contains(endpoint); } /** @@ -211,7 +102,7 @@ public class CommonRestController { final WebTarget webTarget = client.target(fullyQualifiedEndpoint); - return webTarget.request(MediaType.APPLICATION_JSON); + return webTarget.request(MediaType.APPLICATION_JSON).accept(MediaType.APPLICATION_JSON); } /** @@ -259,4 +150,13 @@ public class CommonRestController { Response rawresp = sendNoAuthRequest(endPoint).delete(); assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); } + + /** + * Set Up httpPrefix. + * + * @param port the port + */ + protected void setHttpPrefix(int port) { + httpPrefix = "http://" + SELF + ":" + port + "/"; + } } diff --git a/runtime-controlloop/src/test/resources/application_test.properties b/runtime-controlloop/src/test/resources/application_test.properties new file mode 100644 index 000000000..fc24ea290 --- /dev/null +++ b/runtime-controlloop/src/test/resources/application_test.properties @@ -0,0 +1,9 @@ +spring.security.user.name=healthcheck +spring.security.user.password=zb!XztG34 +security.enable-csrf=false + +server.port=6969 +server.servlet.context-path=/onap/controlloop +server.error.path=/error + +runtime.file=src/test/resources/parameters/TestParameters.json diff --git a/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParametersStd.json b/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParametersStd.json index 3d5a7dfca..06f4370e8 100644 --- a/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParametersStd.json +++ b/runtime-controlloop/src/test/resources/parameters/InstantiationConfigParametersStd.json @@ -6,8 +6,7 @@ "participantClStateChangeIntervalSec": 1000, "restServerParameters": { "host": "0.0.0.0", - "port": ${port - }, + "port": ${port}, "userName": "healthcheck", "password": "zb!XztG34", "https": false, |