From a098edad859459ab116d4587af8262877f2b522a Mon Sep 17 00:00:00 2001 From: talio Date: Wed, 17 Jun 2020 15:57:06 +0300 Subject: Toggle Add toggling mechanism to catalog side. The first toggleable feature is healing - this was added to healing flow, in healJanusGraphDao Issue-ID: SDC-2874 Signed-off-by: talio Change-Id: If386651cab8304ebaf13497ded3a7a50bd60e477 Signed-off-by: talio --- catalog-be/pom.xml | 18 +++ .../be/components/impl/TogglingBusinessLogic.java | 72 +++++++++ .../openecomp/sdc/be/servlets/TogglingServlet.java | 168 +++++++++++++++++++++ .../be/togglz/CassandraCustomStateRepository.java | 3 +- .../sdc/be/togglz/ToggleConfiguration.java | 52 ------- .../src/main/resources/application-context.xml | 3 +- .../src/main/resources/config/features.properties | 1 + catalog-be/src/main/webapp/WEB-INF/web.xml | 137 +++++++++-------- .../togglz/CassandraCustomStateRepositoryTest.java | 1 - 9 files changed, 333 insertions(+), 122 deletions(-) create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/TogglingBusinessLogic.java create mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TogglingServlet.java delete mode 100644 catalog-be/src/main/java/org/openecomp/sdc/be/togglz/ToggleConfiguration.java create mode 100644 catalog-be/src/main/resources/config/features.properties (limited to 'catalog-be') diff --git a/catalog-be/pom.xml b/catalog-be/pom.xml index 47650bd8c7..d0a0f95f8a 100644 --- a/catalog-be/pom.xml +++ b/catalog-be/pom.xml @@ -36,6 +36,18 @@ test + + org.openecomp.sdc + togglz-rest-services + ${project.version} + + + + com.rabbitmq + amqp-client + 3.3.1 + + com.fasterxml.jackson.core @@ -104,6 +116,12 @@ + + javax.ws.rs + javax.ws.rs-api + ${ws.rs.version} + + org.openecomp.sdc.be common-be diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/TogglingBusinessLogic.java b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/TogglingBusinessLogic.java new file mode 100644 index 0000000000..538f565917 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/components/impl/TogglingBusinessLogic.java @@ -0,0 +1,72 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2020 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.openecomp.sdc.be.components.impl; + +import java.util.Arrays; +import java.util.Map; +import java.util.stream.Collectors; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.ArtifactsOperations; +import org.openecomp.sdc.be.model.jsonjanusgraph.operations.InterfaceOperation; +import org.openecomp.sdc.be.model.operations.api.IElementOperation; +import org.openecomp.sdc.be.model.operations.api.IGroupInstanceOperation; +import org.openecomp.sdc.be.model.operations.api.IGroupOperation; +import org.openecomp.sdc.be.model.operations.api.IGroupTypeOperation; +import org.openecomp.sdc.be.model.operations.impl.InterfaceLifecycleOperation; +import org.openecomp.sdc.be.togglz.ToggleableFeature; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.togglz.core.Feature; +import org.togglz.core.context.FeatureContext; +import org.togglz.core.repository.FeatureState; +import org.togglz.core.util.NamedFeature; + +@Component("togglingBusinessLogic") +public class TogglingBusinessLogic extends BaseBusinessLogic { + + @Autowired + public TogglingBusinessLogic(IElementOperation elementDao, IGroupOperation groupOperation, + IGroupInstanceOperation groupInstanceOperation, IGroupTypeOperation groupTypeOperation, + InterfaceOperation interfaceOperation, InterfaceLifecycleOperation interfaceLifecycleTypeOperation, + ArtifactsOperations artifactToscaOperation) { + super(elementDao, groupOperation, groupInstanceOperation, groupTypeOperation, interfaceOperation, + interfaceLifecycleTypeOperation, artifactToscaOperation); + } + + public Map getAllFeatureStates() { + return Arrays.stream(ToggleableFeature.values()).collect(Collectors.toMap(Enum::name, + ToggleableFeature::isActive)); + } + + public boolean getFeatureState(String featureName) { + return ToggleableFeature.valueOf(featureName).isActive(); + } + + public void setAllFeatures(boolean state) { + Arrays.asList(ToggleableFeature.values()) + .forEach(toggleableFeature -> updateFeatureState(toggleableFeature.name(), state)); + } + + public void updateFeatureState(String featureName, boolean state) { + Feature feature = new NamedFeature(featureName); + FeatureState featureState = new FeatureState(feature, state); + FeatureContext.getFeatureManager().setFeatureState(featureState); + } +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TogglingServlet.java b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TogglingServlet.java new file mode 100644 index 0000000000..df53919b59 --- /dev/null +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/servlets/TogglingServlet.java @@ -0,0 +1,168 @@ +/*- + * ============LICENSE_START======================================================= + * SDC + * ================================================================================ + * Copyright (C) 2020 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.openecomp.sdc.be.servlets; + +import com.jcabi.aspects.Loggable; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.media.ArraySchema; +import io.swagger.v3.oas.annotations.media.Content; +import io.swagger.v3.oas.annotations.media.Schema; +import io.swagger.v3.oas.annotations.responses.ApiResponse; +import io.swagger.v3.oas.annotations.servers.Server; +import io.swagger.v3.oas.annotations.servers.Servers; +import io.swagger.v3.oas.annotations.tags.Tag; +import io.swagger.v3.oas.annotations.tags.Tags; +import java.util.Map; +import javax.inject.Inject; +import javax.inject.Singleton; +import javax.servlet.http.HttpServletRequest; +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.PUT; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.Produces; +import javax.ws.rs.core.Context; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.openecomp.sdc.be.components.impl.ComponentInstanceBusinessLogic; +import org.openecomp.sdc.be.components.impl.ResourceImportManager; +import org.openecomp.sdc.be.components.impl.TogglingBusinessLogic; +import org.openecomp.sdc.be.dao.api.ActionStatus; +import org.openecomp.sdc.be.impl.ComponentsUtils; +import org.openecomp.sdc.be.impl.ServletUtils; +import org.openecomp.sdc.be.user.UserBusinessLogic; +import org.openecomp.sdc.common.log.wrappers.Logger; + +@Loggable(prepend = true, value = Loggable.DEBUG, trim = false) +@Path("/v1/catalog/toggle") +@Tags({@Tag(name = "SDC Internal APIs")}) +@Servers({@Server(url = "/sdc2/rest")}) +@Singleton +public class TogglingServlet extends AbstractValidationsServlet { + + private final TogglingBusinessLogic togglingBusinessLogic; + + @Inject + public TogglingServlet(UserBusinessLogic userBusinessLogic, ComponentInstanceBusinessLogic componentInstanceBL, + ComponentsUtils componentsUtils, ServletUtils servletUtils, ResourceImportManager resourceImportManager, + TogglingBusinessLogic togglingBusinessLogic) { + super(userBusinessLogic, componentInstanceBL, componentsUtils, servletUtils, resourceImportManager); + this.togglingBusinessLogic = togglingBusinessLogic; + } + + private static final Logger log = Logger.getLogger(TogglingServlet.class); + private static final String ALL_FEATURES_STATES_WERE_SET_SUCCESSFULLY = "All features states were set successfully"; + private static final String START_HANDLE_REQUEST_OF = "Start handle request of {}"; + private static final String FEATURE_STATE_WAS_UPDATED_SUCCESSFULLY = "Feature state was updated successfully"; + + + @GET + @Path("/") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Get all Toggleable features", method = "GET", summary = "Returns list of toggleable features", responses = { + @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = javax.ws.rs.core.Response.class)))), + @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "404", description = "Toggleable features not found")}) + public Response getAllFeatures(@Context final HttpServletRequest request) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug(START_HANDLE_REQUEST_OF, url); + + try { + Map features = togglingBusinessLogic.getAllFeatureStates(); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), features); + } catch (Exception e) { + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + @GET + @Path("/{featureName}/state") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Get Toggleable feature state", method = "GET", summary = "Returns one toggleable feature state", responses = { + @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = javax.ws.rs.core.Response.class)))), + @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "404", description = "Toggleable feature not found")}) + public Response getToggleableFeature(@PathParam("featureName") String featureName, @Context final HttpServletRequest request) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug(START_HANDLE_REQUEST_OF, url); + + try { + boolean featureState = togglingBusinessLogic.getFeatureState(featureName); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), featureState); + } catch (Exception e) { + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + @PUT + @Path("/state/{state}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Update all feature toggle state", method = "PUT", summary = "Update all feature status", responses = { + @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = javax.ws.rs.core.Response.class)))), + @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "404", description = "Toggleable features not found")}) + public Response setAllFeatures(@PathParam("state") boolean state, @Context final HttpServletRequest request) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug(START_HANDLE_REQUEST_OF, url); + + try { + togglingBusinessLogic.setAllFeatures(state); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), ALL_FEATURES_STATES_WERE_SET_SUCCESSFULLY); + } catch (Exception e) { + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + @PUT + @Path("/{featureName}/state/{state}") + @Consumes(MediaType.APPLICATION_JSON) + @Produces(MediaType.APPLICATION_JSON) + @Operation(description = "Update feature toggle state", method = "PUT", summary = "Update feature status", responses = { + @ApiResponse(content = @Content(array = @ArraySchema(schema = @Schema(implementation = javax.ws.rs.core.Response.class)))), + @ApiResponse(responseCode = "200", description = "Success"), + @ApiResponse(responseCode = "403", description = "Restricted operation"), + @ApiResponse(responseCode = "400", description = "Invalid content / Missing content"), + @ApiResponse(responseCode = "404", description = "Toggleable features not found")}) + public Response updateFeatureState(@PathParam("featureName") String featureName, + @PathParam("state") boolean state, @Context final HttpServletRequest request) { + String url = request.getMethod() + " " + request.getRequestURI(); + log.debug("(get) Start handle request of {}", url); + + try { + togglingBusinessLogic.updateFeatureState(featureName, state); + return buildOkResponse(getComponentsUtils().getResponseFormat(ActionStatus.OK), FEATURE_STATE_WAS_UPDATED_SUCCESSFULLY); + } catch (Exception e) { + return buildErrorResponse(getComponentsUtils().getResponseFormat(ActionStatus.GENERAL_ERROR)); + } + } + + +} diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/togglz/CassandraCustomStateRepository.java b/catalog-be/src/main/java/org/openecomp/sdc/be/togglz/CassandraCustomStateRepository.java index a67bf4b9f4..5e2f416159 100644 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/togglz/CassandraCustomStateRepository.java +++ b/catalog-be/src/main/java/org/openecomp/sdc/be/togglz/CassandraCustomStateRepository.java @@ -24,7 +24,6 @@ import com.google.common.annotations.VisibleForTesting; import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus; import org.openecomp.sdc.be.dao.cassandra.FeatureToggleDao; import org.openecomp.sdc.be.resources.data.togglz.FeatureToggleEvent; -import org.openecomp.sdc.be.resources.data.togglz.ToggleableFeature; import org.openecomp.sdc.common.log.wrappers.Logger; import org.springframework.stereotype.Component; import org.togglz.core.Feature; @@ -38,7 +37,7 @@ import java.util.stream.Collectors; @Component public class CassandraCustomStateRepository implements StateRepository { - private final static Logger logger = Logger.getLogger(CassandraCustomStateRepository.class); + private static final Logger logger = Logger.getLogger(CassandraCustomStateRepository.class); private final FeatureToggleDao featureToggleDao; public CassandraCustomStateRepository(FeatureToggleDao featureToggleDao) { diff --git a/catalog-be/src/main/java/org/openecomp/sdc/be/togglz/ToggleConfiguration.java b/catalog-be/src/main/java/org/openecomp/sdc/be/togglz/ToggleConfiguration.java deleted file mode 100644 index 52bbf86c6e..0000000000 --- a/catalog-be/src/main/java/org/openecomp/sdc/be/togglz/ToggleConfiguration.java +++ /dev/null @@ -1,52 +0,0 @@ -/*- - * ============LICENSE_START======================================================= - * SDC - * ================================================================================ - * Copyright (C) 2020 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.openecomp.sdc.be.togglz; - -import org.openecomp.sdc.be.resources.data.togglz.ToggleableFeature; -import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.stereotype.Component; -import org.togglz.core.Feature; -import org.togglz.core.manager.TogglzConfig; -import org.togglz.core.repository.StateRepository; -import org.togglz.core.repository.cache.CachingStateRepository; -import org.togglz.core.user.SimpleFeatureUser; -import org.togglz.core.user.UserProvider; - -@Component -public class ToggleConfiguration implements TogglzConfig { - @Autowired - private CassandraCustomStateRepository cassandraCustomStateRepository; - - @Override - public Class getFeatureClass() { - return ToggleableFeature.class; - } - - @Override - public StateRepository getStateRepository() { - return new CachingStateRepository(cassandraCustomStateRepository, 10000); - } - - @Override - public UserProvider getUserProvider() { - return () -> new SimpleFeatureUser("admin", true); - } -} \ No newline at end of file diff --git a/catalog-be/src/main/resources/application-context.xml b/catalog-be/src/main/resources/application-context.xml index ca36de1168..403debfb08 100644 --- a/catalog-be/src/main/resources/application-context.xml +++ b/catalog-be/src/main/resources/application-context.xml @@ -14,7 +14,8 @@ org.openecomp.sdc.be.servlets, org.openecomp.sdc.be.externalapi.servlet, org.openecomp.sdc.be.components.scheduledtasks, - org.openecomp.sdc.be.facade.operations"> + org.openecomp.sdc.be.facade.operations, + org.openecomp.sdc.be.components.impl"> diff --git a/catalog-be/src/main/resources/config/features.properties b/catalog-be/src/main/resources/config/features.properties new file mode 100644 index 0000000000..488a78fa81 --- /dev/null +++ b/catalog-be/src/main/resources/config/features.properties @@ -0,0 +1 @@ +HEALING=false \ No newline at end of file diff --git a/catalog-be/src/main/webapp/WEB-INF/web.xml b/catalog-be/src/main/webapp/WEB-INF/web.xml index 9991e30a86..23a08319ff 100644 --- a/catalog-be/src/main/webapp/WEB-INF/web.xml +++ b/catalog-be/src/main/webapp/WEB-INF/web.xml @@ -20,10 +20,10 @@ org.openecomp.sdc.be.filters.BeServletFilter, org.openecomp.sdc.be.filters.ComponentsAvailabilityFilter, org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature, - org.openecomp.sdc.be.servlets.exception.DefaultExceptionMapper, + org.openecomp.sdc.be.servlets.exception.DefaultExceptionMapper, org.openecomp.sdc.be.servlets.exception.ComponentExceptionMapper, org.openecomp.sdc.be.servlets.exception.ConstraintViolationExceptionMapper, - org.openecomp.sdc.be.servlets.exception.StorageExceptionMapper, + org.openecomp.sdc.be.servlets.exception.StorageExceptionMapper, org.openecomp.sdc.be.view.MixinModelWriter, org.openecomp.sdc.config.ObjectMapperProvider @@ -81,29 +81,29 @@ true - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + ViewStatusMessages @@ -151,10 +151,10 @@ - - - - + + + + gatewayFilter @@ -173,35 +173,35 @@ /sdc/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + reqValidationFilter @@ -224,14 +224,19 @@ java.lang.RuntimeException /sdc2/rest/v1/catalog/handleException/ - - contextConfigLocation - classpath:application-context.xml - - - - org.openecomp.sdc.be.listen.BEAppContextListener - + + contextConfigLocation + classpath:application-context.xml + + + + org.togglz.core.manager.TogglzConfig + org.openecomp.sdc.be.togglz.TogglzConfiguration + + + + org.openecomp.sdc.be.listen.BEAppContextListener + org.springframework.web.context.ContextLoaderListener diff --git a/catalog-be/src/test/java/org/openecomp/sdc/be/togglz/CassandraCustomStateRepositoryTest.java b/catalog-be/src/test/java/org/openecomp/sdc/be/togglz/CassandraCustomStateRepositoryTest.java index 7786f6ef91..2560c04202 100644 --- a/catalog-be/src/test/java/org/openecomp/sdc/be/togglz/CassandraCustomStateRepositoryTest.java +++ b/catalog-be/src/test/java/org/openecomp/sdc/be/togglz/CassandraCustomStateRepositoryTest.java @@ -29,7 +29,6 @@ import org.mockito.junit.MockitoJUnitRunner; import org.openecomp.sdc.be.dao.cassandra.CassandraOperationStatus; import org.openecomp.sdc.be.dao.cassandra.FeatureToggleDao; import org.openecomp.sdc.be.resources.data.togglz.FeatureToggleEvent; -import org.openecomp.sdc.be.resources.data.togglz.ToggleableFeature; import org.togglz.core.Feature; import org.togglz.core.repository.FeatureState; -- cgit 1.2.3-korg