Add REST Endpoints for ACM test microservice 85/130385/2
authorrameshiyer27 <ramesh.murugan.iyer@est.tech>
Fri, 19 Aug 2022 09:08:16 +0000 (10:08 +0100)
committerrameshiyer27 <ramesh.murugan.iyer@est.tech>
Fri, 19 Aug 2022 09:55:12 +0000 (10:55 +0100)
REST APIs for activating, deactivating and fetching the element config.

Issue-ID: POLICY-4305
Signed-off-by: zrrmmua <ramesh.murugan.iyer@est.tech>
Change-Id: Ib3cf41fe5419c9fd05743bb3c66b19e95a797b98

participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/config/FilterConfig.java [new file with mode: 0644]
participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessageHandler.java
participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/handler/MessagePublisher.java
participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/rest/AbstractRestController.java [new file with mode: 0644]
participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/rest/AcElementController.java
participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/rest/GlobalControllerExceptionHandler.java
participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/service/ConfigService.java
participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/rest/AcElementControllerTest.java [new file with mode: 0644]
participant/participant-impl/participant-impl-acelement/src/test/resources/config.json [new file with mode: 0644]

diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/config/FilterConfig.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/config/FilterConfig.java
new file mode 100644 (file)
index 0000000..1b447a0
--- /dev/null
@@ -0,0 +1,44 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.acm.element.config;
+
+import org.onap.policy.clamp.common.acm.rest.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/policy/clamp/acelement/v2/*");
+        return registrationBean;
+    }
+}
index 540c133..63b0ebc 100644 (file)
@@ -29,10 +29,10 @@ import lombok.Getter;
 import lombok.NonNull;
 import org.onap.policy.clamp.acm.element.main.parameters.AcElement;
 import org.onap.policy.clamp.acm.element.service.ElementService;
+import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException;
 import org.onap.policy.clamp.models.acm.messages.dmaap.element.ElementMessage;
 import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig;
 import org.onap.policy.clamp.models.acm.messages.rest.element.ElementType;
-import org.onap.policy.models.base.PfModelRuntimeException;
 import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
 import org.springframework.stereotype.Component;
 
@@ -75,10 +75,10 @@ public class MessageHandler {
      */
     public void update(@NonNull ElementConfig elementConfig) {
         if (elementType == null) {
-            throw new PfModelRuntimeException(Response.Status.CONFLICT, "ElementType not defined!");
+            throw new AutomationCompositionRuntimeException(Response.Status.CONFLICT, "ElementType not defined!");
         }
         if (!elementType.equals(elementConfig.getElementType())) {
-            throw new PfModelRuntimeException(Response.Status.CONFLICT, "wrong ElementType!");
+            throw new AutomationCompositionRuntimeException(Response.Status.CONFLICT, "wrong ElementType!");
         }
         getActiveService().update(elementConfig);
     }
@@ -90,11 +90,11 @@ public class MessageHandler {
      */
     public ElementService getActiveService() {
         if (elementType == null) {
-            throw new PfModelRuntimeException(Response.Status.CONFLICT, "ElementType not defined!");
+            throw new AutomationCompositionRuntimeException(Response.Status.CONFLICT, "ElementType not defined!");
         }
         var service = map.get(elementType);
         if (service == null) {
-            throw new PfModelRuntimeException(Response.Status.CONFLICT, "ElementService not found!");
+            throw new AutomationCompositionRuntimeException(Response.Status.CONFLICT, "ElementService not found!");
         }
         return service;
     }
index ef0a72f..928a4fe 100644 (file)
@@ -22,10 +22,10 @@ package org.onap.policy.clamp.acm.element.handler;
 
 import java.util.List;
 import javax.ws.rs.core.Response;
+import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException;
 import org.onap.policy.clamp.models.acm.messages.dmaap.element.ElementMessage;
 import org.onap.policy.common.endpoints.event.comm.TopicSink;
 import org.onap.policy.common.endpoints.event.comm.client.TopicSinkClient;
-import org.onap.policy.models.base.PfModelRuntimeException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
@@ -58,7 +58,7 @@ public class MessagePublisher {
      */
     public void publishMsg(final ElementMessage msg) {
         if (!active) {
-            throw new PfModelRuntimeException(Response.Status.CONFLICT, NOT_ACTIVE_TEXT);
+            throw new AutomationCompositionRuntimeException(Response.Status.CONFLICT, NOT_ACTIVE_TEXT);
         }
 
         topicSinkClient.send(msg);
diff --git a/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/rest/AbstractRestController.java b/participant/participant-impl/participant-impl-acelement/src/main/java/org/onap/policy/clamp/acm/element/main/rest/AbstractRestController.java
new file mode 100644 (file)
index 0000000..408458f
--- /dev/null
@@ -0,0 +1,96 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2022 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.acm.element.main.rest;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.BasicAuthDefinition;
+import io.swagger.annotations.Info;
+import io.swagger.annotations.SecurityDefinition;
+import io.swagger.annotations.SwaggerDefinition;
+import io.swagger.annotations.Tag;
+import java.net.HttpURLConnection;
+import javax.ws.rs.core.MediaType;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+/**
+ * Common superclass to provide REST endpoints for the AC element.
+ */
+// @formatter:off
+@RequestMapping(
+        value = "/v2",
+        produces = {
+            MediaType.APPLICATION_JSON,
+            AbstractRestController.APPLICATION_YAML
+        }
+)
+@Api(value = "AC Element API")
+@SwaggerDefinition(
+        info = @Info(
+                description = "AC Element",
+                version = "v1.0",
+                title = "AC Element"
+        ),
+        consumes = {MediaType.APPLICATION_JSON, AbstractRestController.APPLICATION_YAML},
+        produces = {MediaType.APPLICATION_JSON, AbstractRestController.APPLICATION_YAML},
+        schemes = {SwaggerDefinition.Scheme.HTTP, SwaggerDefinition.Scheme.HTTPS},
+        tags = {
+            @Tag(name = "acelement", description = "Ac element implementation")
+        },
+        securityDefinition = @SecurityDefinition(basicAuthDefinitions = {@BasicAuthDefinition(key = "basicAuth")})
+)
+// @formatter:on
+public abstract class AbstractRestController {
+    public static final String APPLICATION_YAML = "application/yaml";
+
+    public static final String EXTENSION_NAME = "interface info";
+
+    public static final String API_VERSION_NAME = "api-version";
+    public static final String API_VERSION = "1.0.0";
+
+    public static final String LAST_MOD_NAME = "last-mod-release";
+    public static final String LAST_MOD_RELEASE = "Dublin";
+
+    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";
+
+    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";
+
+    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";
+
+    public static final String REQUEST_ID_NAME = "X-ONAP-RequestID";
+    public static final String REQUEST_ID_HDR_DESCRIPTION = "Used to track REST transactions for logging purpose";
+
+    public static final String AUTHORIZATION_TYPE = "basicAuth";
+
+    public static final int AUTHENTICATION_ERROR_CODE = HttpURLConnection.HTTP_UNAUTHORIZED;
+    public static final int AUTHORIZATION_ERROR_CODE = HttpURLConnection.HTTP_FORBIDDEN;
+    public static final int SERVER_ERROR_CODE = HttpURLConnection.HTTP_INTERNAL_ERROR;
+
+    public static final String AUTHENTICATION_ERROR_MESSAGE = "Authentication Error";
+    public static final String AUTHORIZATION_ERROR_MESSAGE = "Authorization Error";
+    public static final String SERVER_ERROR_MESSAGE = "Internal Server Error";
+
+}
\ No newline at end of file
index 833819a..7a8662c 100644 (file)
 
 package org.onap.policy.clamp.acm.element.main.rest;
 
+import io.swagger.annotations.ApiOperation;
+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.UUID;
+import lombok.RequiredArgsConstructor;
+import org.onap.policy.clamp.acm.element.service.ConfigService;
+import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig;
+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.RestController;
 
 @RestController
-public class AcElementController {
+@RequiredArgsConstructor
+public class AcElementController extends AbstractRestController {
 
-    //TODO : Implement REST methods for configuring Dmaap topic
-}
+    private final ConfigService configService;
+
+
+    /**
+     * REST endpoint to get the existing element config.
+     *
+     * @return the element config params
+     */
+    // @formatter:off
+    @GetMapping(path = "/config", produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation(
+            value = "Return the element config",
+            response = ElementConfig.class,
+            tags = {
+                "Clamp Automation Composition AC Element Impl 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<ElementConfig> getElementConfig() {
+        return new ResponseEntity<>(configService.getElementConfig(), HttpStatus.OK);
+    }
+
+    /**
+     * REST endpoint to activate the element.
+     *
+     * @param params element parameters for this ac element
+     */
+    // @formatter:off
+    @PostMapping(path = "/activate", consumes = MediaType.APPLICATION_JSON_VALUE,
+         produces = MediaType.APPLICATION_JSON_VALUE)
+    @ApiOperation(
+        value = "Activates the element config",
+        response = ElementConfig.class,
+        tags = {
+            "Clamp Automation Composition AC Element Impl 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<Object> activateElement(@RequestBody ElementConfig params) {
+        configService.activateElement(params);
+        return new ResponseEntity<>(HttpStatus.CREATED);
+    }
+
+    /**
+     * REST endpoint to delete the element config.
+     *
+     * @return Status of operation
+     */
+    // @formatter:off
+    @DeleteMapping(path = "/deactivate")
+    @ApiOperation(
+        value = "Delete the element config",
+        response = ElementConfig.class,
+        tags = {
+            "Clamp Automation Composition AC Element Impl 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<Object> deleteConfig()  {
+        configService.deleteConfig();
+        return new ResponseEntity<>(HttpStatus.NO_CONTENT);
+
+    }
+}
\ No newline at end of file
index bb56bf9..41dcbef 100644 (file)
@@ -22,7 +22,7 @@
 
 package org.onap.policy.clamp.acm.element.main.rest;
 
-import org.onap.policy.clamp.common.acm.exception.AutomationCompositionException;
+import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException;
 import org.onap.policy.clamp.models.acm.messages.rest.SimpleResponse;
 import org.onap.policy.clamp.models.acm.rest.RestUtils;
 import org.springframework.http.ResponseEntity;
@@ -38,8 +38,8 @@ public class GlobalControllerExceptionHandler {
      * @param ex AutomationCompositionException
      * @return ResponseEntity
      */
-    @ExceptionHandler(AutomationCompositionException.class)
-    public ResponseEntity<SimpleResponse> handleBadRequest(AutomationCompositionException ex) {
+    @ExceptionHandler(AutomationCompositionRuntimeException.class)
+    public ResponseEntity<SimpleResponse> handleBadRequest(AutomationCompositionRuntimeException ex) {
         return RestUtils.toSimpleResponse(ex);
     }
 }
index f542be2..f8f9024 100644 (file)
@@ -26,11 +26,11 @@ import lombok.NonNull;
 import lombok.RequiredArgsConstructor;
 import org.onap.policy.clamp.acm.element.handler.MessageActivator;
 import org.onap.policy.clamp.acm.element.handler.MessageHandler;
+import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException;
 import org.onap.policy.clamp.models.acm.messages.dmaap.element.ElementMessage;
 import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig;
 import org.onap.policy.common.endpoints.parameters.TopicParameterGroup;
 import org.onap.policy.common.endpoints.parameters.TopicParameters;
-import org.onap.policy.models.base.PfModelRuntimeException;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Service;
@@ -64,12 +64,12 @@ public class ConfigService {
         parameters.setTopicSources(List.of(topicParameters));
 
         if (!parameters.isValid()) {
-            throw new PfModelRuntimeException(Response.Status.BAD_REQUEST,
+            throw new AutomationCompositionRuntimeException(Response.Status.BAD_REQUEST,
                     "Validation failed for topic parameter group. Kafka config not activated");
         }
 
         if (messageActivator.isAlive()) {
-            throw new PfModelRuntimeException(Response.Status.CONFLICT,
+            throw new AutomationCompositionRuntimeException(Response.Status.CONFLICT,
                     "Service Manager already running, cannot add Topic endpoint management");
         }
 
diff --git a/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/rest/AcElementControllerTest.java b/participant/participant-impl/participant-impl-acelement/src/test/java/org/onap/policy/clamp/acm/element/rest/AcElementControllerTest.java
new file mode 100644 (file)
index 0000000..c40cdea
--- /dev/null
@@ -0,0 +1,169 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2022 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.acm.element.rest;
+
+import static org.hamcrest.CoreMatchers.is;
+import static org.junit.Assert.assertEquals;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doThrow;
+import static org.mockito.Mockito.when;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
+import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.StandardCharsets;
+import javax.ws.rs.core.Response;
+import org.apache.commons.io.FileUtils;
+import org.json.JSONObject;
+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.acm.element.main.parameters.AcElement;
+import org.onap.policy.clamp.acm.element.main.rest.AcElementController;
+import org.onap.policy.clamp.acm.element.service.ConfigService;
+import org.onap.policy.clamp.common.acm.exception.AutomationCompositionRuntimeException;
+import org.onap.policy.clamp.models.acm.messages.rest.element.ElementConfig;
+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.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.properties.EnableConfigurationProperties;
+import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.MediaType;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.test.web.servlet.MockMvc;
+import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
+import org.springframework.test.web.servlet.setup.MockMvcBuilders;
+import org.springframework.web.context.WebApplicationContext;
+
+
+@ExtendWith(SpringExtension.class)
+@WebMvcTest(value = AcElementController.class)
+@EnableConfigurationProperties(value = AcElement.class)
+class AcElementControllerTest {
+
+    private static final Coder CODER = new StandardCoder();
+    private static final String ELEMENT_CONFIG_YAML = "src/test/resources/config.json";
+    private static final String RETRIEVE_CONFIG = "/v2/config";
+    private static final String ACTIVATE_CONFIG = "/v2/activate";
+    private static final String DEACTIVATE_CONFIG = "/v2/deactivate";
+    private static ElementConfig config;
+
+
+    @Autowired
+    private MockMvc mockMvc;
+
+    @MockBean
+    private ConfigService configService;
+
+    @Autowired
+    private WebApplicationContext context;
+
+    /**
+     * Read input element config json.
+     * @throws CoderException in case of error.
+     */
+    @BeforeAll
+    static void setupParams() throws CoderException {
+        config = CODER.decode(new File(ELEMENT_CONFIG_YAML), ElementConfig.class);
+    }
+
+    /**
+     * Mock service layer in Controller.
+     */
+    @BeforeEach
+    void mockServiceClass() {
+        this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build();
+        when(configService.getElementConfig()).thenReturn(config);
+    }
+
+    /**
+     * Test endpoint for retrieving element config.
+     * @throws Exception in case of error.
+     */
+    @Test
+    void retrieveElementConfig() throws Exception {
+        var requestBuilder = MockMvcRequestBuilders.get(RETRIEVE_CONFIG)
+                .accept(MediaType.APPLICATION_JSON_VALUE);
+
+        mockMvc.perform(requestBuilder).andExpect(status().isOk())
+                .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON))
+                .andExpect(jsonPath("$.elementType", is("STARTER")));
+    }
+
+    /**
+     * Test endpoint for activating element config.
+     * @throws Exception in case of error.
+     */
+    @Test
+    void activateConfig() throws Exception {
+        //Mocking successful activation of element config
+        doNothing().when(configService).activateElement(config);
+
+        var requestBuilder = MockMvcRequestBuilders.post(ACTIVATE_CONFIG)
+                .accept(MediaType.APPLICATION_JSON_VALUE)
+                .content(getElementConfigJson())
+                .contentType(MediaType.APPLICATION_JSON_VALUE);
+
+        mockMvc.perform(requestBuilder).andExpect(status().isCreated());
+
+        doThrow(new AutomationCompositionRuntimeException(Response.Status.CONFLICT, "service manager already running"))
+                .when(configService).activateElement(any());
+
+        //Activate Invalid config, expects HTTP status CONFLICT
+        requestBuilder = MockMvcRequestBuilders.post(ACTIVATE_CONFIG).accept(MediaType.APPLICATION_JSON_VALUE)
+                .content(getInvalidJson())
+                .contentType(MediaType.APPLICATION_JSON_VALUE);
+
+        mockMvc.perform(requestBuilder).andExpect(status().isConflict())
+                .andExpect(result -> assertEquals("service manager already running",
+                        result.getResolvedException().getMessage()));
+    }
+
+    /**
+     * Test endpoint for deactivating element config.
+     * @throws Exception in case of error.
+     */
+    @Test
+    void deActivateConfig() throws Exception {
+
+        //Mocking successful deactivation of element config
+        doNothing().when(configService).deleteConfig();
+
+        var requestBuilder = MockMvcRequestBuilders.delete(DEACTIVATE_CONFIG);
+
+        mockMvc.perform(requestBuilder).andExpect(status().isNoContent());
+    }
+
+    private String getInvalidJson() {
+        return new JSONObject().toString();
+    }
+
+    private String getElementConfigJson() throws IOException {
+        return FileUtils.readFileToString(new File(ELEMENT_CONFIG_YAML), StandardCharsets.UTF_8);
+    }
+
+}
diff --git a/participant/participant-impl/participant-impl-acelement/src/test/resources/config.json b/participant/participant-impl/participant-impl-acelement/src/test/resources/config.json
new file mode 100644 (file)
index 0000000..bf45182
--- /dev/null
@@ -0,0 +1,14 @@
+{
+  "elementId":{
+    "name":"onap.policy.clamp.ac.element2",
+    "version":"1.0.0"
+  },
+  "timerSec":2000,
+  "elementType":"STARTER",
+  "topicParameterGroup":{
+    "server":"localhost",
+    "topic":"POLICY_UPDATE_MSG",
+    "fetchTimeout":15000,
+    "topicCommInfrastructure":"dmaap"
+  }
+}
\ No newline at end of file