diff options
Diffstat (limited to 'dcae-analytics/dcae-analytics-tca-web/src')
38 files changed, 2965 insertions, 0 deletions
diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/TcaAppMain.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/TcaAppMain.java new file mode 100644 index 0000000..5b8c8ea --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/TcaAppMain.java @@ -0,0 +1,42 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web; + +import org.onap.dcae.analytics.tca.web.config.TcaWebConfig; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.SpringBootConfiguration; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Import; +import org.springframework.integration.config.EnableIntegration; + +/** + * @author Rajiv Singla + */ +@Import(value = {TcaWebConfig.class}) +@EnableIntegration +@SpringBootConfiguration +@EnableAutoConfiguration +public class TcaAppMain { + + public static void main(String[] args) { + SpringApplication.run(TcaAppMain.class, args); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/TcaAppProperties.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/TcaAppProperties.java new file mode 100644 index 0000000..9ee625a --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/TcaAppProperties.java @@ -0,0 +1,86 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web; + +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import org.onap.dcae.analytics.model.TcaModelConstants; +import org.onap.dcae.analytics.model.configbindingservice.BaseConfigBindingServiceProperties; +import org.onap.dcae.analytics.model.configbindingservice.ConfigBindingServiceConstants; +import org.onap.dcae.analytics.model.configbindingservice.ConfigBindingServiceModel; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.validation.annotation.Validated; + +/** + * @author Rajiv Singla + */ +@Data +@EqualsAndHashCode(callSuper = true) +@ConfigurationProperties(ConfigBindingServiceConstants.CONFIG_BINDING_SERVICE_PROPERTIES_KEY) +@Validated +public class TcaAppProperties extends BaseConfigBindingServiceProperties { + + private static final long serialVersionUID = 1L; + + private Tca tca; + + /** + * TCA Application properties + */ + @Data + public static class Tca implements ConfigBindingServiceModel { + + private static final long serialVersionUID = 1L; + + private String policy; + private Integer processingBatchSize = TcaModelConstants.DEFAULT_TCA_PROCESSING_BATCH_SIZE; + private Boolean enableAbatement = TcaModelConstants.DEFAULT_ABATEMENT_ENABLED; + private Boolean enableEcompLogging = TcaModelConstants.DEFAULT_ECOMP_LOGGING_ENABLED; + private Aai aai = new Aai(); + + } + + + /** + * A&AI properties + */ + @Data + @ToString(exclude = "password") + public static class Aai implements ConfigBindingServiceModel { + + private static final long serialVersionUID = 1L; + + private Boolean enableEnrichment = TcaModelConstants.DEFAULT_AAI_ENRICHMENT_ENABLED; + private String url; + private String username; + private String password; + + private String proxyUrl = null; + private Boolean ignoreSSLValidation = TcaModelConstants.DEFAULT_TCA_AAI_IGNORE_SSL_VALIDATION; + + private String genericVnfPath = TcaModelConstants.DEFAULT_TCA_AAI_GENERIC_VNF_PATH; + private String nodeQueryPath = TcaModelConstants.DEFAULT_TCA_AAI_NODE_QUERY_PATH; + + } + + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/aai/TcaAaiEnrichmentContextImpl.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/aai/TcaAaiEnrichmentContextImpl.java new file mode 100644 index 0000000..73a600a --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/aai/TcaAaiEnrichmentContextImpl.java @@ -0,0 +1,50 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.aai; + +import org.onap.dcae.analytics.tca.core.service.TcaAaiEnrichmentContext; +import org.onap.dcae.analytics.tca.core.service.TcaAaiEnrichmentService; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; + +/** + * @author Rajiv Singla + */ +public class TcaAaiEnrichmentContextImpl implements TcaAaiEnrichmentContext { + + private final TcaAppProperties tcaAppProperties; + private final TcaAaiEnrichmentService tcaAaiEnrichmentService; + + public TcaAaiEnrichmentContextImpl(final TcaAppProperties tcaAppProperties, + final TcaAaiEnrichmentService tcaAaiEnrichmentService) { + this.tcaAppProperties = tcaAppProperties; + this.tcaAaiEnrichmentService = tcaAaiEnrichmentService; + } + + + @Override + public boolean isAaiEnrichmentEnabled() { + return tcaAppProperties.getTca().getAai().getEnableEnrichment(); + } + + @Override + public TcaAaiEnrichmentService getAaiEnrichmentService() { + return tcaAaiEnrichmentService; + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/aai/TcaAaiEnrichmentServiceImpl.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/aai/TcaAaiEnrichmentServiceImpl.java new file mode 100644 index 0000000..d38bd23 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/aai/TcaAaiEnrichmentServiceImpl.java @@ -0,0 +1,273 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.aai; + +import static org.onap.dcae.analytics.tca.model.util.json.TcaModelJsonConversion.TCA_OBJECT_MAPPER; + +import com.fasterxml.jackson.databind.JsonNode; + +import java.io.IOException; +import java.net.URI; +import java.util.Collections; +import java.util.Iterator; +import java.util.Map; +import java.util.Set; + +import org.onap.dcae.analytics.model.AnalyticsHttpConstants; +import org.onap.dcae.analytics.model.TcaModelConstants; +import org.onap.dcae.analytics.tca.core.service.TcaAaiEnrichmentService; +import org.onap.dcae.analytics.tca.core.service.TcaExecutionContext; +import org.onap.dcae.analytics.tca.model.facade.Aai; +import org.onap.dcae.analytics.tca.model.facade.TcaAlert; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpEntity; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpMethod; +import org.springframework.http.ResponseEntity; +import org.springframework.util.StringUtils; +import org.springframework.web.client.RestTemplate; +import org.springframework.web.util.UriComponentsBuilder; + +/** + * @author Rajiv Singla + */ +public class TcaAaiEnrichmentServiceImpl implements TcaAaiEnrichmentService { + + private static final Logger logger = LoggerFactory.getLogger(TcaAaiEnrichmentServiceImpl.class); + + private final TcaAppProperties tcaAppProperties; + private final RestTemplate aaiRestTemplate; + + public TcaAaiEnrichmentServiceImpl(final TcaAppProperties tcaAppProperties, + final RestTemplate aaiRestTemplate) { + this.tcaAppProperties = tcaAppProperties; + this.aaiRestTemplate = aaiRestTemplate; + } + + + @Override + public TcaAlert doAaiEnrichment(final TcaExecutionContext tcaExecutionContext) { + + final TcaAlert tcaAlert = tcaExecutionContext.getTcaResultContext().getTcaAlert(); + + // do aai enrichment + if (isVNFAlert(tcaAlert)) { + // do vnf enrichment + doAaiVnfEnrichment(tcaExecutionContext, aaiRestTemplate, tcaAppProperties); + } else { + // do vm enrichment + doAaiVmEnrichment(tcaExecutionContext, aaiRestTemplate, tcaAppProperties); + } + + return tcaAlert; + } + + private static void doAaiVmEnrichment(final TcaExecutionContext tcaExecutionContext, + final RestTemplate aaiRestTemplate, + final TcaAppProperties tcaAppProperties) { + + final TcaAlert tcaAlert = tcaExecutionContext.getTcaResultContext().getTcaAlert(); + final String requestId = tcaExecutionContext.getRequestId(); + final String transactionId = tcaExecutionContext.getTransactionId(); + final String vServerName = tcaAlert.getAai().getGenericServerName(); + + // create new node query uri + final TcaAppProperties.Aai aai = tcaAppProperties.getTca().getAai(); + final URI nodeQueryUri = UriComponentsBuilder.fromHttpUrl(aai.getUrl()) + .path(aai.getNodeQueryPath()) + .queryParam("search-node-type", "vserver") + .queryParam("filter", "vserver-name:EQUALS:" + vServerName) + .build(Collections.emptyMap()); + + // get resource link + final String resourceLink = + getVMResourceLink(getAAIRestAPIResponse(aaiRestTemplate, nodeQueryUri, requestId, transactionId)); + if (resourceLink == null) { + return; + } + + // create virtual server enrichment uri + final URI vServerEnrichmentUri = UriComponentsBuilder.fromHttpUrl(aai.getUrl()) + .path(resourceLink) + .build(Collections.emptyMap()); + + // fetch virtual server enrichment details + final String vServerEnrichmentDetails = + getAAIRestAPIResponse(aaiRestTemplate, vServerEnrichmentUri, requestId, transactionId); + + // do aai enrichment + enrichAAI(vServerEnrichmentDetails, tcaAlert, TcaModelConstants.AAI_VSERVER_KEY_PREFIX); + } + + private static void doAaiVnfEnrichment(final TcaExecutionContext tcaExecutionContext, + final RestTemplate aaiRestTemplate, + final TcaAppProperties tcaAppProperties) { + + final TcaAlert tcaAlert = tcaExecutionContext.getTcaResultContext().getTcaAlert(); + final String requestId = tcaExecutionContext.getRequestId(); + final String transactionId = tcaExecutionContext.getTransactionId(); + final String genericVnfName = tcaAlert.getAai().getGenericVNFName(); + + // create new generic vnf uri + final TcaAppProperties.Aai aai = tcaAppProperties.getTca().getAai(); + final URI genericVnfUri = UriComponentsBuilder.fromHttpUrl(aai.getUrl()) + .path(aai.getGenericVnfPath()) + .queryParam("vnf-name", genericVnfName) + .build(Collections.emptyMap()); + + // fetch response + final String aaiResponse = getAAIRestAPIResponse(aaiRestTemplate, genericVnfUri, requestId, transactionId); + + // do AAI enrichment + enrichAAI(aaiResponse, tcaAlert, TcaModelConstants.AAI_VNF_KEY_PREFIX); + } + + + /** + * Fetch response from A&AI Rest API as json string for given aai uri. Returns null if unable to fetch response + * from A&AI API + * + * @param aaiRestTemplate aai rest template + * @param aaiUri aai uri + * + * @return A&AI API response as json string + */ + private static String getAAIRestAPIResponse(final RestTemplate aaiRestTemplate, final URI aaiUri, + final String requestId, final String transactionId) { + // fetch response + ResponseEntity<String> aaiResponseEntity = null; + try { + final HttpHeaders headers = new HttpHeaders(); + headers.add(AnalyticsHttpConstants.REQUEST_ID_HEADER_KEY, requestId); + headers.add(AnalyticsHttpConstants.REQUEST_TRANSACTION_ID_HEADER_KEY, transactionId); + final HttpEntity<String> httpEntity = new HttpEntity<>(headers); + aaiResponseEntity = aaiRestTemplate.exchange(aaiUri, HttpMethod.GET, httpEntity, String.class); + } catch (Exception e) { + logger.debug("Request id: " + requestId + ". Unable to get A&AI enrichment details", e); + } + + if (aaiResponseEntity != null && aaiResponseEntity.getStatusCode().is2xxSuccessful()) { + return aaiResponseEntity.getBody(); + } + + return null; + } + + + /** + * Populates A&AI details retrieved from A&AI Enrichment API into Alerts A&AI Object + * + * @param aaiEnrichmentDetails A&AI Enrichment API fetched JSON String + * @param tcaAlert tca alert + * @param keyPrefix Key prefix that needs to be added to each fetched A&AI Enrichment record + * + * @return true if A&AI enrichment completed successfully + */ + private static boolean enrichAAI(final String aaiEnrichmentDetails, final TcaAlert tcaAlert, + final String keyPrefix) { + + final Aai preEnrichmentAAI = tcaAlert.getAai(); + if (aaiEnrichmentDetails == null) { + logger.warn("Request id: {}. No A&AI Enrichment possible. A&AI Enrichment details are absent.", + tcaAlert.getRequestId()); + return false; + } + + final Aai enrichedAAI = getNewEnrichedAAI(aaiEnrichmentDetails); + + if (enrichedAAI != null) { + final Set<Map.Entry<String, Object>> enrichedAAIEntrySet = + enrichedAAI.getDynamicProperties().entrySet(); + final Map<String, Object> preEnrichmentAAIDynamicProperties = preEnrichmentAAI.getDynamicProperties(); + + // populate Alert A&AI Enrichment details and add prefix to key + for (Map.Entry<String, Object> enrichedAAIEntry : enrichedAAIEntrySet) { + preEnrichmentAAIDynamicProperties.put( + keyPrefix + enrichedAAIEntry.getKey(), enrichedAAIEntry.getValue()); + } + + logger.debug("Request id: {}. A&AI Enrichment was completed successfully.", tcaAlert.getRequestId()); + return true; + } else { + logger.warn("Request id: {}. No A&AI Enrichment possible. Skipped - Invalid A&AI Response.", + tcaAlert.getRequestId()); + return false; + } + + } + + /** + * Creates a new A&AI object with only top level A&AI Enrichment details + * + * @param aaiEnrichmentDetails A&AI Enrichment details + * + * @return new A&AI with only top level A&AI Enrichment details + */ + private static Aai getNewEnrichedAAI(final String aaiEnrichmentDetails) { + try { + final JsonNode rootNode = TCA_OBJECT_MAPPER.readTree(aaiEnrichmentDetails); + final Iterator<Map.Entry<String, JsonNode>> fieldsIterator = rootNode.fields(); + while (fieldsIterator.hasNext()) { + final Map.Entry<String, JsonNode> fieldEntry = fieldsIterator.next(); + final JsonNode jsonNode = fieldEntry.getValue(); + // remove all arrays, objects from A&AI Enrichment Json + if (jsonNode.isPojo() || jsonNode.isObject() || jsonNode.isArray()) { + fieldsIterator.remove(); + } + } + return TCA_OBJECT_MAPPER.treeToValue(rootNode, Aai.class); + } catch (IOException e) { + logger.error( + "Failed to Parse AAI Enrichment Details from JSON: {}, Exception: {}.", aaiEnrichmentDetails, e); + } + return null; + } + + /** + * Fetches VM Object Resource Link from A&AI Resource Link Json + * + * @param vmAAIResourceLinkDetails VM Object Resource Link from A&AI Resource Link Json + * + * @return object resource link String + */ + private static String getVMResourceLink(final String vmAAIResourceLinkDetails) { + if (StringUtils.hasText(vmAAIResourceLinkDetails)) { + try { + final JsonNode jsonNode = TCA_OBJECT_MAPPER.readTree(vmAAIResourceLinkDetails); + final JsonNode resourceLinkJsonNode = jsonNode.findPath("resource-link"); + if (!resourceLinkJsonNode.isMissingNode()) { + return resourceLinkJsonNode.asText(); + } + } catch (IOException e) { + logger.error("Unable to determine VM Object link inside AAI Resource Link Response JSON: {}", + vmAAIResourceLinkDetails, e); + } + } + return null; + } + + + private static boolean isVNFAlert(final TcaAlert tcaAlert) { + return tcaAlert.getTargetType().equals(TcaModelConstants.TCA_ALERT_VNF_TARGET_TYPE); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/aai/TcaAaiRestClientPreferences.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/aai/TcaAaiRestClientPreferences.java new file mode 100644 index 0000000..93a54a9 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/aai/TcaAaiRestClientPreferences.java @@ -0,0 +1,48 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.aai; + +import java.net.URL; + +import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import org.onap.dcae.analytics.web.http.BaseHttpClientPreferences; +import org.springframework.http.HttpHeaders; + +/** + * @author Rajiv Singla + */ +public class TcaAaiRestClientPreferences extends BaseHttpClientPreferences { + + private static final long serialVersionUID = 1L; + + public TcaAaiRestClientPreferences(@Nonnull final String requestURL, + @Nullable final String httpClientId, + @Nullable final HttpHeaders httpHeaders, + @Nullable final String username, + @Nullable final String password, + @Nullable final URL proxyURL, + @Nullable final Boolean ignoreSSLValidation, + @Nullable final Boolean enableEcompAuditLogging) { + super(requestURL, httpClientId, httpHeaders, username, password, proxyURL, ignoreSSLValidation, + enableEcompAuditLogging); + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/mongo/MongoAbatementContextImpl.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/mongo/MongoAbatementContextImpl.java new file mode 100644 index 0000000..a4784e0 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/mongo/MongoAbatementContextImpl.java @@ -0,0 +1,58 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.abatement.mongo; + +import org.onap.dcae.analytics.tca.core.service.TcaAbatementContext; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementEntity; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementRepository; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; + +/** + * An implementation of {@link TcaAbatementContext} backed by mongo database as persistence provider + * + * @author Rajiv Singla + */ +public class MongoAbatementContextImpl implements TcaAbatementContext { + + private TcaAppProperties tcaAppProperties; + private MongoAbatementRepository mongoAbatementRepository; + + public MongoAbatementContextImpl(final TcaAppProperties tcaAppProperties, + final MongoAbatementRepository mongoAbatementRepository) { + this.tcaAppProperties = tcaAppProperties; + this.mongoAbatementRepository = mongoAbatementRepository; + } + + @Override + public boolean isAbatementEnabled() { + return tcaAppProperties.getTca().getEnableAbatement(); + } + + @Override + public TcaAbatementRepository getTcaAbatementRepository() { + return mongoAbatementRepository; + } + + @Override + public TcaAbatementEntity create(final String lookupKey, final String requestId, + final boolean isAbatementAlertSent) { + return new MongoAbatementEntity(lookupKey, requestId, isAbatementAlertSent); + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/mongo/MongoAbatementEntity.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/mongo/MongoAbatementEntity.java new file mode 100644 index 0000000..562c918 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/mongo/MongoAbatementEntity.java @@ -0,0 +1,59 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.abatement.mongo; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +import org.onap.dcae.analytics.tca.core.service.TcaAbatementEntity; +import org.onap.dcae.analytics.tca.model.TcaModel; +import org.springframework.data.annotation.CreatedDate; +import org.springframework.data.annotation.Id; +import org.springframework.data.annotation.LastModifiedDate; +import org.springframework.data.mongodb.core.mapping.Document; + +/** + * @author Rajiv Singla + */ +@Data +@NoArgsConstructor +@Document(collection = "tca_abatement") +public class MongoAbatementEntity implements TcaAbatementEntity, TcaModel { + + private static final long serialVersionUID = 1L; + + @Id + private String lookupKey; + private String requestId; + private boolean isAbatementAlertSent; + + @LastModifiedDate + private Date lastModificationDate; + @CreatedDate + private Date createdDate; + + MongoAbatementEntity(final String lookupKey, final String requestId, final boolean isAbatementAlertSent) { + this.lookupKey = lookupKey; + this.requestId = requestId; + this.isAbatementAlertSent = isAbatementAlertSent; + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/mongo/MongoAbatementRepository.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/mongo/MongoAbatementRepository.java new file mode 100644 index 0000000..6727007 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/mongo/MongoAbatementRepository.java @@ -0,0 +1,36 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.abatement.mongo; + +import java.util.List; + +import org.bson.types.ObjectId; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementEntity; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementRepository; +import org.springframework.data.mongodb.repository.MongoRepository; + +/** + * @author Rajiv Singla + */ +public interface MongoAbatementRepository extends + TcaAbatementRepository, MongoRepository<MongoAbatementEntity, ObjectId> { + + List<TcaAbatementEntity> findByLookupKey(final String lookUpKey); +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/simple/SimpleAbatementContextImpl.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/simple/SimpleAbatementContextImpl.java new file mode 100644 index 0000000..6c17039 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/simple/SimpleAbatementContextImpl.java @@ -0,0 +1,62 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.abatement.simple; + +import org.onap.dcae.analytics.tca.core.service.TcaAbatementContext; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementEntity; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementRepository; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; + +/** + * A simple implementation for {@link TcaAbatementContext} which should be used for testing and development + * purposes only. + * + * @author Rajiv Singla + */ +public class SimpleAbatementContextImpl implements TcaAbatementContext { + + + private final TcaAppProperties tcaAppProperties; + private final TcaAbatementRepository tcaAbatementRepository; + + public SimpleAbatementContextImpl(final TcaAppProperties tcaAppProperties, + final TcaAbatementRepository tcaAbatementRepository) { + this.tcaAppProperties = tcaAppProperties; + this.tcaAbatementRepository = tcaAbatementRepository; + } + + + @Override + public boolean isAbatementEnabled() { + return tcaAppProperties.getTca().getEnableAbatement(); + } + + @Override + public TcaAbatementRepository getTcaAbatementRepository() { + return tcaAbatementRepository; + } + + @Override + public TcaAbatementEntity create(final String lookupKey, final String requestId, + final boolean isAbatementAlertSent) { + return new SimpleAbatementEntity(lookupKey, requestId, isAbatementAlertSent); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/simple/SimpleAbatementEntity.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/simple/SimpleAbatementEntity.java new file mode 100644 index 0000000..c12306f --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/simple/SimpleAbatementEntity.java @@ -0,0 +1,58 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.abatement.simple; + +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.Date; + +import org.onap.dcae.analytics.tca.core.service.TcaAbatementEntity; +import org.onap.dcae.analytics.tca.model.TcaModel; + +/** + * @author Rajiv Singla + */ +@Data +@NoArgsConstructor +public class SimpleAbatementEntity implements TcaAbatementEntity, TcaModel { + + private static final long serialVersionUID = 1L; + + protected String lookupKey; + protected String requestId; + protected boolean isAbatementAlertSent; + protected Date lastModificationDate; + + SimpleAbatementEntity(final String lookupKey, final String requestId, final boolean isAbatementAlertSent) { + this.lookupKey = lookupKey; + this.requestId = requestId; + this.isAbatementAlertSent = isAbatementAlertSent; + this.lastModificationDate = new Date(); + } + + public Date getLastModificationDate() { + return new Date(lastModificationDate.getTime()); + } + + public void setLastModificationDate(final Date lastModificationDate) { + this.lastModificationDate = new Date(lastModificationDate.getTime()); + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/simple/SimpleAbatementRepository.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/simple/SimpleAbatementRepository.java new file mode 100644 index 0000000..452f07f --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/abatement/simple/SimpleAbatementRepository.java @@ -0,0 +1,89 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.abatement.simple; + +import static org.onap.dcae.analytics.model.TcaModelConstants.TCA_ABATEMENT_SIMPLE_REPOSITORY_MAX_ENTITY_COUNT; +import static org.onap.dcae.analytics.model.TcaModelConstants.TCA_ABATEMENT_SIMPLE_REPOSITORY_REMOVE_ENTITY_COUNT; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentLinkedQueue; + +import org.onap.dcae.analytics.tca.core.service.TcaAbatementEntity; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementRepository; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * A simple implementation for {@link TcaAbatementRepository} which should be used for testing and development + * purposes only. + * + * @author Rajiv Singla + */ +public class SimpleAbatementRepository implements TcaAbatementRepository { + + private static final Logger logger = LoggerFactory.getLogger(SimpleAbatementRepository.class); + + private final ConcurrentLinkedQueue<String> lookupKeysQueue; + private final ConcurrentHashMap<String, SimpleAbatementEntity> repository; + + public SimpleAbatementRepository() { + this.lookupKeysQueue = new ConcurrentLinkedQueue<>(); + this.repository = new ConcurrentHashMap<>(TCA_ABATEMENT_SIMPLE_REPOSITORY_MAX_ENTITY_COUNT); + } + + + @Override + public synchronized void save(final TcaAbatementEntity tcaAbatementEntity) { + + // remove entries from repository if required + if (lookupKeysQueue.size() == TCA_ABATEMENT_SIMPLE_REPOSITORY_MAX_ENTITY_COUNT) { + + logger.warn("Simple Abatement Repository reached its max allowed size: {}, " + + "Removing last inserted {} entries", + TCA_ABATEMENT_SIMPLE_REPOSITORY_MAX_ENTITY_COUNT, + TCA_ABATEMENT_SIMPLE_REPOSITORY_REMOVE_ENTITY_COUNT); + + for (int i = 0; i < TCA_ABATEMENT_SIMPLE_REPOSITORY_REMOVE_ENTITY_COUNT; i++) { + final String lookupKey = lookupKeysQueue.poll(); + logger.warn("Removing Abatement Lookup key: {} from Simple Abatement Repository", lookupKey); + repository.remove(lookupKey); + } + + } + + lookupKeysQueue.add(tcaAbatementEntity.getLookupKey()); + final SimpleAbatementEntity simpleAbatementEntity = + new SimpleAbatementEntity(tcaAbatementEntity.getLookupKey(), tcaAbatementEntity.getRequestId(), + tcaAbatementEntity.isAbatementAlertSent()); + repository.put(tcaAbatementEntity.getLookupKey(), simpleAbatementEntity); + + } + + @Override + public List<TcaAbatementEntity> findByLookupKey(final String lookUpKey) { + final SimpleAbatementEntity repoEntity = repository.getOrDefault(lookUpKey, null); + if (repoEntity == null) { + return Collections.emptyList(); + } + return Collections.singletonList(repoEntity); + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/ControllerConfig.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/ControllerConfig.java new file mode 100644 index 0000000..930786e --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/ControllerConfig.java @@ -0,0 +1,41 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.config; + +import org.onap.dcae.analytics.tca.web.controller.TcaRestController; +import org.onap.dcae.analytics.tca.web.domain.TcaPolicyWrapper; +import org.onap.dcae.analytics.tca.web.service.TcaProcessingService; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Rajiv Singla + */ +@Configuration +public class ControllerConfig { + + @Bean + public TcaRestController tcaRestController(final TcaPolicyWrapper tcaPolicyWrapper, + final TcaProcessingService tcaProcessingService) { + return new TcaRestController(tcaProcessingService, tcaPolicyWrapper); + } + + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/SwaggerConfig.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/SwaggerConfig.java new file mode 100644 index 0000000..11fa97c --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/SwaggerConfig.java @@ -0,0 +1,63 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.config; + +import static org.onap.dcae.analytics.model.TcaModelConstants.TCA_REST_API_PREFIX; + +import springfox.documentation.builders.ApiInfoBuilder; +import springfox.documentation.builders.PathSelectors; +import springfox.documentation.builders.RequestHandlerSelectors; +import springfox.documentation.service.ApiInfo; +import springfox.documentation.spi.DocumentationType; +import springfox.documentation.spring.web.plugins.Docket; +import springfox.documentation.swagger2.annotations.EnableSwagger2; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * @author Rajiv Singla + */ +@Configuration +@EnableSwagger2 +public class SwaggerConfig { + + @Bean + public Docket apiDocker() { + return new Docket(DocumentationType.SWAGGER_2) + .apiInfo(getApiInfo()) + .useDefaultResponseMessages(false) + .select() + .apis(RequestHandlerSelectors.basePackage("org.onap.dcae.analytics.tca.web.controller")) + .paths(PathSelectors.ant(TCA_REST_API_PREFIX + "**")) + .build(); + } + + + private static ApiInfo getApiInfo() { + return new ApiInfoBuilder() + .title("TCA (Threshold Crossing Alert) Analytics RESTful API") + .description("RESTful API for Threshold Crossing Alerts Analytics") + .license("Apache License Version 2.0") + .version("3.0") + .build(); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaAaiConfig.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaAaiConfig.java new file mode 100644 index 0000000..773b9d3 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaAaiConfig.java @@ -0,0 +1,67 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.config; + +import org.onap.dcae.analytics.tca.core.service.TcaAaiEnrichmentContext; +import org.onap.dcae.analytics.tca.core.service.TcaAaiEnrichmentService; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.tca.web.aai.TcaAaiEnrichmentContextImpl; +import org.onap.dcae.analytics.tca.web.aai.TcaAaiEnrichmentServiceImpl; +import org.onap.dcae.analytics.tca.web.aai.TcaAaiRestClientPreferences; +import org.onap.dcae.analytics.tca.web.util.function.TcaAppPropsToAaiRestClientPrefsFunction; +import org.onap.dcae.analytics.web.http.HttpClientPreferencesCustomizer; +import org.springframework.boot.web.client.RestTemplateBuilder; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.web.client.RestTemplate; + +/** + * @author Rajiv Singla + */ +@Configuration +public class TcaAaiConfig { + + @Bean + public TcaAaiRestClientPreferences aaiRestClientPreferences(final TcaAppProperties tcaAppProperties) { + return new TcaAppPropsToAaiRestClientPrefsFunction().apply(tcaAppProperties); + } + + @Bean + public RestTemplate aaiRestTemplate(final TcaAaiRestClientPreferences aaiRestClientPreferences, + final RestTemplateBuilder restTemplateBuilder) { + return restTemplateBuilder + .additionalCustomizers(new HttpClientPreferencesCustomizer<>(aaiRestClientPreferences)) + .build(); + } + + @Bean + public TcaAaiEnrichmentService aaiEnrichmentService(final TcaAppProperties tcaAppProperties, + final RestTemplate aaiRestTemplate) { + return new TcaAaiEnrichmentServiceImpl(tcaAppProperties, aaiRestTemplate); + } + + + @Bean + public TcaAaiEnrichmentContext tcaAaiEnrichmentContext(final TcaAppProperties tcaAppProperties, + final TcaAaiEnrichmentService aaiEnrichmentService) { + return new TcaAaiEnrichmentContextImpl(tcaAppProperties, aaiEnrichmentService); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaMongoAbatementConfig.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaMongoAbatementConfig.java new file mode 100644 index 0000000..7b29f15 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaMongoAbatementConfig.java @@ -0,0 +1,48 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.config; + +import org.onap.dcae.analytics.model.AnalyticsProfile; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementContext; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.tca.web.abatement.mongo.MongoAbatementContextImpl; +import org.onap.dcae.analytics.tca.web.abatement.mongo.MongoAbatementRepository; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.data.mongodb.config.EnableMongoAuditing; +import org.springframework.data.mongodb.repository.config.EnableMongoRepositories; + +/** + * @author Rajiv Singla + */ +@Configuration +@Profile(AnalyticsProfile.MONGO_PROFILE_NAME) +@EnableMongoRepositories("org.onap.dcae.analytics.tca.web.abatement.mongo") +@EnableMongoAuditing +public class TcaMongoAbatementConfig { + + @Bean + public TcaAbatementContext mongoAbatementContext(final TcaAppProperties tcaAppProperties, + final MongoAbatementRepository mongoAbatementRepository) { + return new MongoAbatementContextImpl(tcaAppProperties, mongoAbatementRepository); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaMrConfig.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaMrConfig.java new file mode 100644 index 0000000..64cb6eb --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaMrConfig.java @@ -0,0 +1,114 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.config; + +import static org.onap.dcae.analytics.model.AnalyticsHttpConstants.REQUEST_ID_HEADER_KEY; +import static org.onap.dcae.analytics.model.AnalyticsHttpConstants.REQUEST_TRANSACTION_ID_HEADER_KEY; + +import java.util.List; +import java.util.Map; + +import org.onap.dcae.analytics.model.AnalyticsProfile; +import org.onap.dcae.analytics.model.DmaapMrConstants; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.tca.web.domain.TcaPolicyWrapper; +import org.onap.dcae.analytics.tca.web.integration.TcaAlertTransformer; +import org.onap.dcae.analytics.tca.web.integration.TcaPublisherResponseHandler; +import org.onap.dcae.analytics.tca.web.service.TcaProcessingService; +import org.onap.dcae.analytics.tca.web.util.function.TcaAppPropsToMrPublisherPrefsFunction; +import org.onap.dcae.analytics.tca.web.util.function.TcaAppPropsToMrSubscriberPrefsFunction; +import org.onap.dcae.analytics.web.dmaap.MrPublisherPreferences; +import org.onap.dcae.analytics.web.dmaap.MrSubscriberPreferences; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; +import org.springframework.integration.channel.DirectChannel; +import org.springframework.integration.channel.NullChannel; +import org.springframework.integration.channel.QueueChannel; +import org.springframework.integration.dsl.IntegrationFlow; +import org.springframework.integration.dsl.IntegrationFlows; +import org.springframework.messaging.MessageHeaders; + +/** + * @author Rajiv Singla + */ +@Profile({AnalyticsProfile.DMAAP_PROFILE_NAME}) +@Configuration +public class TcaMrConfig { + + @Bean + public MrSubscriberPreferences mrSubscriberPreferences(final TcaAppProperties tcaAppProperties) { + return new TcaAppPropsToMrSubscriberPrefsFunction().apply(tcaAppProperties); + } + + @Bean + public MrPublisherPreferences mrPublisherPreferences(final TcaAppProperties tcaAppProperties) { + return new TcaAppPropsToMrPublisherPrefsFunction().apply(tcaAppProperties); + } + + @Bean + public Integer processingBatchSize(final TcaAppProperties tcaAppProperties) { + return tcaAppProperties.getTca().getProcessingBatchSize(); + } + + @Bean + public TcaAlertTransformer tcaAlertTransformer(final TcaAppProperties tcaAppProperties) { + return new TcaAlertTransformer(tcaAppProperties); + } + + + @Bean + public IntegrationFlow tcaMrFlow(final TcaPolicyWrapper tcaPolicyWrapper, + final QueueChannel mrSubscriberOutputChannel, + final DirectChannel mrPublisherInputChannel, + final TcaProcessingService tcaProcessingService, + final TcaAlertTransformer tcaAlertTransformer) { + // get messages from dmaap subscriber channel + return IntegrationFlows.from(mrSubscriberOutputChannel) + // handle incoming message from dmaap + .handle((List<String> cefMessages, Map<String, Object> headers) -> + tcaProcessingService.getTcaExecutionResults( + headers.getOrDefault(REQUEST_ID_HEADER_KEY, headers.get(MessageHeaders.ID)).toString(), + headers.getOrDefault(REQUEST_TRANSACTION_ID_HEADER_KEY, "").toString(), + tcaPolicyWrapper.getTcaPolicy(), cefMessages)) + // transform tca execution results to alerts - if not alerts are detected terminate further processing + .transform(tcaAlertTransformer, c -> c.requiresReply(false)) + // post messages to dmaap publisher input channel + .channel(mrPublisherInputChannel) + .get(); + } + + + @Bean + public TcaPublisherResponseHandler tcaPublisherResponseHandler(final TcaAppProperties tcaAppProperties) { + return new TcaPublisherResponseHandler(tcaAppProperties); + } + + @Bean + public IntegrationFlow tcaPublisherResponseFlow(final TcaPublisherResponseHandler tcaPublisherResponseHandler) { + return IntegrationFlows.from(DmaapMrConstants.DMAAP_MR_PUBLISHER_OUTPUT_CHANNEL) + // log response from dmaap publisher output channel + .handle(tcaPublisherResponseHandler) + // finish processing + .channel(new NullChannel()) + .get(); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaSimpleAbatementConfig.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaSimpleAbatementConfig.java new file mode 100644 index 0000000..9f8cb92 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaSimpleAbatementConfig.java @@ -0,0 +1,50 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.config; + +import org.onap.dcae.analytics.model.AnalyticsProfile; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementContext; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementRepository; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.tca.web.abatement.simple.SimpleAbatementContextImpl; +import org.onap.dcae.analytics.tca.web.abatement.simple.SimpleAbatementRepository; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Profile; + +/** + * @author Rajiv Singla + */ +@Configuration +@Profile(AnalyticsProfile.NOT_MONGO_PROFILE_NAME) +public class TcaSimpleAbatementConfig { + + @Bean + public TcaAbatementRepository simpleAbatementRepository() { + return new SimpleAbatementRepository(); + } + + @Bean + public TcaAbatementContext tcaAbatementContext(final TcaAppProperties tcaAppProperties, + final TcaAbatementRepository tcaAbatementRepository) { + return new SimpleAbatementContextImpl(tcaAppProperties, tcaAbatementRepository); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaWebConfig.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaWebConfig.java new file mode 100644 index 0000000..7be20cc --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/config/TcaWebConfig.java @@ -0,0 +1,84 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.config; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.stream.Stream; + +import org.onap.dcae.analytics.model.AnalyticsProfile; +import org.onap.dcae.analytics.model.common.ConfigSource; +import org.onap.dcae.analytics.tca.core.service.TcaAaiEnrichmentContext; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementContext; +import org.onap.dcae.analytics.tca.model.util.json.TcaModelJsonConversion; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.tca.web.domain.TcaPolicyWrapper; +import org.onap.dcae.analytics.tca.web.service.TcaProcessingService; +import org.onap.dcae.analytics.tca.web.service.TcaProcessingServiceImpl; +import org.onap.dcae.analytics.tca.web.validation.TcaAppPropertiesValidator; +import org.onap.dcae.analytics.web.config.AnalyticsWebConfig; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; +import org.springframework.core.env.Environment; +import org.springframework.validation.Validator; + +/** + * @author Rajiv Singla + */ +@Configuration +@EnableConfigurationProperties(value = TcaAppProperties.class) +@Import(value = {AnalyticsWebConfig.class, TcaMrConfig.class, TcaAaiConfig.class, + TcaMongoAbatementConfig.class, TcaSimpleAbatementConfig.class, SwaggerConfig.class, ControllerConfig.class}) +public class TcaWebConfig { + + @Bean + public static Validator configurationPropertiesValidator() { + return new TcaAppPropertiesValidator(); + } + + @Bean + public ObjectMapper objectMapper() { + return TcaModelJsonConversion.TCA_OBJECT_MAPPER; + } + + @Bean + public TcaPolicyWrapper tcaPolicyWrapper(final TcaAppProperties tcaAppProperties, + final Environment environment) { + final String policy = tcaAppProperties.getTca().getPolicy(); + final boolean isConfigBindingServiceProfileActive = + Stream.of(environment.getActiveProfiles()) + .anyMatch(profile -> + profile.equalsIgnoreCase(AnalyticsProfile.CONFIG_BINDING_SERVICE_PROFILE_NAME)); + if (isConfigBindingServiceProfileActive) { + return new TcaPolicyWrapper(policy, ConfigSource.CONFIG_BINDING_SERVICE); + } else { + return new TcaPolicyWrapper(policy, ConfigSource.CLASSPATH); + } + } + + @Bean + public TcaProcessingService tcaProcessingService(final TcaAbatementContext tcaAbatementContext, + final TcaAaiEnrichmentContext tcaAaiEnrichmentContext) { + return new TcaProcessingServiceImpl(tcaAbatementContext, tcaAaiEnrichmentContext); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/controller/TcaRestController.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/controller/TcaRestController.java new file mode 100644 index 0000000..eb9eb13 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/controller/TcaRestController.java @@ -0,0 +1,114 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.controller; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; + +import java.time.format.DateTimeFormatter; +import java.util.List; +import java.util.stream.Collectors; + +import org.onap.dcae.analytics.model.TcaModelConstants; +import org.onap.dcae.analytics.model.common.ConfigSource; +import org.onap.dcae.analytics.tca.core.service.TcaExecutionContext; +import org.onap.dcae.analytics.tca.core.service.TcaResultContext; +import org.onap.dcae.analytics.tca.model.policy.TcaPolicy; +import org.onap.dcae.analytics.tca.model.restapi.TcaExecutionRequest; +import org.onap.dcae.analytics.tca.model.restapi.TcaExecutionResponse; +import org.onap.dcae.analytics.tca.web.domain.TcaPolicyWrapper; +import org.onap.dcae.analytics.tca.web.service.TcaProcessingService; +import org.onap.dcae.analytics.tca.web.util.TcaUtils; +import org.springframework.http.MediaType; +import org.springframework.http.ResponseEntity; +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.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +/** + * @author Rajiv Singla + */ +@RestController +@RequestMapping(TcaModelConstants.TCA_REST_API_PREFIX) +@Api(value = "Provides endpoints for TCA micro service") +public class TcaRestController { + + private final TcaProcessingService tcaProcessingService; + private final TcaPolicyWrapper tcaPolicyWrapper; + + + public TcaRestController(final TcaProcessingService tcaProcessingService, + final TcaPolicyWrapper tcaPolicyWrapper) { + this.tcaProcessingService = tcaProcessingService; + this.tcaPolicyWrapper = tcaPolicyWrapper; + } + + @GetMapping(value = TcaModelConstants.TCA_POLICY_ENDPOINT, produces = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation(value = "Provides current TCA Policy") + public ResponseEntity<TcaPolicy> getTcaPolicy() { + return getTcaPolicyResponse(tcaPolicyWrapper); + } + + @PostMapping(value = TcaModelConstants.TCA_POLICY_ENDPOINT, produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation(value = "Sets new value for TCA Policy and returns current Policy") + public ResponseEntity<TcaPolicy> setTcaPolicy(@RequestBody final TcaPolicy tcaPolicy) { + tcaPolicyWrapper.setTcaPolicy(tcaPolicy, ConfigSource.REST_API); + return getTcaPolicyResponse(tcaPolicyWrapper); + } + + + @PostMapping(value = TcaModelConstants.TCA_EXECUTION_ENDPOINT, produces = MediaType.APPLICATION_JSON_VALUE, + consumes = MediaType.APPLICATION_JSON_VALUE) + @ApiOperation(value = "Applies TCA to provided execution request and generated TCA execution response") + public ResponseEntity<List<TcaExecutionResponse>> execute(@RequestBody final TcaExecutionRequest + tcaExecutionRequest) { + // process tca execution request + final List<TcaExecutionContext> executionContexts = tcaProcessingService.getTcaExecutionResults( + tcaExecutionRequest.getRequestId(), tcaExecutionRequest.getTransactionId(), + tcaExecutionRequest.getTcaPolicy(), TcaUtils.getCefMessagesFromEventListeners + (tcaExecutionRequest.getEventListeners())); + // create execution response + final List<TcaExecutionResponse> tcaExecutionResponses = executionContexts.stream().map(tcaExecutionContext -> { + final TcaExecutionResponse tcaExecutionResponse = new TcaExecutionResponse(); + tcaExecutionResponse.setRequestId(tcaExecutionContext.getRequestId()); + tcaExecutionResponse.setTransactionId(tcaExecutionContext.getTransactionId()); + final TcaResultContext tcaResultContext = tcaExecutionContext.getTcaResultContext(); + tcaExecutionResponse.setViolatedMetricsPerEventName(tcaResultContext.getViolatedMetricsPerEventName()); + tcaExecutionResponse.setTcaAlert(tcaResultContext.getTcaAlert()); + return tcaExecutionResponse; + }).collect(Collectors.toList()); + + return ResponseEntity.ok().body(tcaExecutionResponses); + } + + + private static ResponseEntity<TcaPolicy> getTcaPolicyResponse(final TcaPolicyWrapper tcaPolicyWrapper) { + return ResponseEntity.ok() + .header(TcaModelConstants.TCA_POLICY_SOURCE_HEADER_KEY, tcaPolicyWrapper.getConfigSource().name()) + .header(TcaModelConstants.TCA_POLICY_CREATION_HEADER_KEY, + tcaPolicyWrapper.getCreationTime().format(DateTimeFormatter.ISO_OFFSET_DATE_TIME)) + .header(TcaModelConstants.TCA_POLICY_VERSION_HEADER_KEY, tcaPolicyWrapper.getPolicyVersion()) + .body(tcaPolicyWrapper.getTcaPolicy()); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/domain/TcaPolicyWrapper.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/domain/TcaPolicyWrapper.java new file mode 100644 index 0000000..e85932a --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/domain/TcaPolicyWrapper.java @@ -0,0 +1,98 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.domain; + +import static org.onap.dcae.analytics.tca.model.util.json.TcaModelJsonConversion.TCA_POLICY_JSON_FUNCTION; + +import lombok.Getter; +import lombok.ToString; + +import java.time.ZonedDateTime; +import java.util.concurrent.atomic.AtomicInteger; + +import org.onap.dcae.analytics.model.common.ConfigSource; +import org.onap.dcae.analytics.tca.model.policy.TcaPolicy; +import org.onap.dcae.analytics.tca.model.policy.TcaPolicyModel; +import org.onap.dcae.analytics.tca.web.validation.TcaPolicyValidator; +import org.onap.dcae.analytics.web.exception.AnalyticsParsingException; +import org.onap.dcae.analytics.web.util.ValidationUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * @author Rajiv Singla + */ +@Getter +@ToString +public class TcaPolicyWrapper implements TcaPolicyModel { + + private static final long serialVersionUID = 1L; + + private static final Logger logger = LoggerFactory.getLogger(TcaPolicyWrapper.class); + + private final ZonedDateTime creationTime; + private ZonedDateTime updateDateTime; + private TcaPolicy tcaPolicy; + private ConfigSource configSource; + private AtomicInteger policyUpdateSequence; + private String policyVersion; + + public TcaPolicyWrapper(final String tcaPolicyString, final ConfigSource configSource) { + createOrUpdatePolicy(getTcaPolicy(tcaPolicyString), configSource); + this.creationTime = ZonedDateTime.now(); + } + + public void setTcaPolicy(final String tcaPolicyString, final ConfigSource configSource) { + createOrUpdatePolicy(getTcaPolicy(tcaPolicyString), configSource); + } + + public void setTcaPolicy(final TcaPolicy tcaPolicy, final ConfigSource configSource) { + createOrUpdatePolicy(tcaPolicy, configSource); + } + + private void createOrUpdatePolicy(final TcaPolicy tcaPolicy, final ConfigSource configSource) { + ValidationUtils.validate(tcaPolicy, new TcaPolicyValidator()); + this.tcaPolicy = tcaPolicy; + this.configSource = configSource; + this.updateDateTime = ZonedDateTime.now(); + if (policyUpdateSequence == null) { + policyUpdateSequence = new AtomicInteger(0); + } else { + policyUpdateSequence.getAndUpdate(sequence -> sequence + 1); + } + this.policyVersion = getPolicyVersion(policyUpdateSequence); + final String configSourceName = configSource.name(); + logger.info("Updated Tca Policy Wrapper with policy: {}, from Source: {}, policy Version: {}", + tcaPolicy, configSourceName, policyVersion); + } + + + private TcaPolicy getTcaPolicy(final String tcaPolicyString) { + return TCA_POLICY_JSON_FUNCTION.apply(tcaPolicyString).orElseThrow( + () -> new AnalyticsParsingException("Unable to parse Tca Policy String: " + tcaPolicyString, + new IllegalArgumentException())); + } + + + private static String getPolicyVersion(final AtomicInteger policyUpdateSequence) { + return "version-" + policyUpdateSequence.intValue(); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/integration/TcaAlertTransformer.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/integration/TcaAlertTransformer.java new file mode 100644 index 0000000..59acd2d --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/integration/TcaAlertTransformer.java @@ -0,0 +1,159 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.integration; + +import java.util.Date; +import java.util.List; +import java.util.Objects; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.onap.dcae.analytics.model.AnalyticsHttpConstants; +import org.onap.dcae.analytics.model.TcaModelConstants; +import org.onap.dcae.analytics.model.ecomplogger.AnalyticsErrorType; +import org.onap.dcae.analytics.tca.core.service.TcaExecutionContext; +import org.onap.dcae.analytics.tca.model.facade.TcaAlert; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.tca.web.util.TcaUtils; +import org.onap.dcae.analytics.web.util.AnalyticsHttpUtils; +import org.onap.dcae.utils.eelf.logger.api.info.ErrorLogInfo; +import org.onap.dcae.utils.eelf.logger.api.info.ResponseLogInfo; +import org.onap.dcae.utils.eelf.logger.api.info.TargetServiceLogInfo; +import org.onap.dcae.utils.eelf.logger.api.log.EELFLogFactory; +import org.onap.dcae.utils.eelf.logger.api.log.EELFLogger; +import org.onap.dcae.utils.eelf.logger.model.info.ErrorLogInfoImpl; +import org.onap.dcae.utils.eelf.logger.model.info.RequestIdLogInfoImpl; +import org.onap.dcae.utils.eelf.logger.model.info.RequestTimingLogInfoImpl; +import org.onap.dcae.utils.eelf.logger.model.info.ResponseLogInfoImpl; +import org.onap.dcae.utils.eelf.logger.model.info.TargetServiceLogInfoImpl; +import org.onap.dcae.utils.eelf.logger.model.spec.AuditLogSpecImpl; +import org.onap.dcae.utils.eelf.logger.model.spec.ErrorLogSpecImpl; +import org.springframework.integration.transformer.AbstractTransformer; +import org.springframework.messaging.Message; + +/** + * @author Rajiv Singla + */ +public class TcaAlertTransformer extends AbstractTransformer { + + private static final EELFLogger logger = EELFLogFactory.getLogger(TcaAlertTransformer.class); + + private static final Predicate<TcaExecutionContext> ERROR_EXECUTION_CONTEXT_PREDICATE = + executionContext -> executionContext.getTcaProcessingContext().getErrorMessage() != null; + private static final Predicate<TcaExecutionContext> EARLY_TERMINATION_CONTEXT_PREDICATE = + tcaExecutionContext -> tcaExecutionContext.getTcaProcessingContext().getEarlyTerminationMessage() != null; + private static final Predicate<TcaExecutionContext> ABATED_EXECUTION_CONTEXT_PREDICATE = + tcaExecutionContext -> tcaExecutionContext.getTcaResultContext().getPreviousRequestId() != null; + + private final TcaAppProperties tcaAppProperties; + + public TcaAlertTransformer(final TcaAppProperties tcaAppProperties) { + this.tcaAppProperties = tcaAppProperties; + } + + + @Override + @SuppressWarnings("unchecked") + protected Object doTransform(final Message<?> message) throws Exception { + + final Object messagePayload = message.getPayload(); + + final String requestId = AnalyticsHttpUtils.getRequestId(message.getHeaders()); + final String transactionId = AnalyticsHttpUtils.getTransactionId(message.getHeaders()); + final Date requestBeginTimestamp = AnalyticsHttpUtils.getTimestampFromHeaders(message.getHeaders(), + AnalyticsHttpConstants.REQUEST_BEGIN_TS_HEADER_KEY); + + if (messagePayload instanceof List) { + // get execution contexts with alerts + final List<TcaExecutionContext> tcaExecutionContexts = (List<TcaExecutionContext>) messagePayload; + final List<TcaAlert> tcaAlerts = + tcaExecutionContexts.stream() + .map(e -> e.getTcaResultContext().getTcaAlert()) + .filter(Objects::nonNull).collect(Collectors.toList()); + + // do ecomp logging + if (tcaAppProperties.getTca().getEnableEcompLogging()) { + final List<TcaExecutionContext> errorExecutionContexts = + tcaExecutionContexts.stream().filter(ERROR_EXECUTION_CONTEXT_PREDICATE) + .collect(Collectors.toList()); + createAuditLog(requestId, transactionId, requestBeginTimestamp, tcaExecutionContexts, tcaAlerts, + errorExecutionContexts); + createErrorLog(requestId, transactionId, errorExecutionContexts); + } + + // if no alerts terminate further processing + return tcaAlerts.isEmpty() ? null : tcaAlerts; + } else { + return null; + } + } + + + private static void createErrorLog(final String requestId, + final String transactionId, + final List<TcaExecutionContext> errorExecutionContexts) { + // no error log generated - if there was no error during tca processing + if (!errorExecutionContexts.isEmpty()) { + for (TcaExecutionContext errorExecutionContext : errorExecutionContexts) { + final RequestIdLogInfoImpl requestIdLogInfo = + new RequestIdLogInfoImpl(errorExecutionContext.getRequestId()); + final TargetServiceLogInfo targetServiceLogInfo = new TargetServiceLogInfoImpl( + "DCAE-TCA", TcaModelConstants.TCA_SERVICE_NAME, ""); + final ErrorLogInfo errorLogInfo = + new ErrorLogInfoImpl(AnalyticsErrorType.SCHEMA_ERROR.getErrorCode(), + AnalyticsErrorType.SCHEMA_ERROR.getErrorDescription()); + final ErrorLogSpecImpl errorLogSpec = new ErrorLogSpecImpl(requestIdLogInfo, + TcaUtils.TCA_SERVICE_LOG_INFO, targetServiceLogInfo, errorLogInfo); + logger.errorLog().error("Request Id: {}, Transaction Id: {}, Error Message: {} ", + errorLogSpec, requestId, transactionId, errorExecutionContext.getTcaProcessingContext() + .getErrorMessage()); + } + } + } + + private static void createAuditLog(final String requestId, + final String transactionId, + final Date requestBeginTimestamp, + final List<TcaExecutionContext> tcaExecutionContexts, + final List<TcaAlert> tcaAlerts, + final List<TcaExecutionContext> errorExecutionContexts) { + final List<TcaExecutionContext> earlyTerminationExecutionContexts = + tcaExecutionContexts.stream().filter(EARLY_TERMINATION_CONTEXT_PREDICATE) + .collect(Collectors.toList()); + final List<TcaExecutionContext> abatedExecutionContexts = + tcaExecutionContexts.stream().filter(ABATED_EXECUTION_CONTEXT_PREDICATE) + .collect(Collectors.toList()); + final RequestIdLogInfoImpl requestIdLogInfo = new RequestIdLogInfoImpl(requestId); + final Date endTimestamp = new Date(); + final RequestTimingLogInfoImpl requestTimingLogInfo = new RequestTimingLogInfoImpl(requestBeginTimestamp, + endTimestamp, endTimestamp.getTime() - requestBeginTimestamp.getTime()); + final ResponseLogInfo responseLogInfo = + new ResponseLogInfoImpl(AnalyticsErrorType.SUCCESSFUL.getErrorCode(), + AnalyticsErrorType.SUCCESSFUL.getErrorDescription()); + final AuditLogSpecImpl auditLogSpec = new AuditLogSpecImpl(requestIdLogInfo, TcaUtils.TCA_SERVICE_LOG_INFO, + requestTimingLogInfo, responseLogInfo); + logger.auditLog().info("Request Id: {}, Transaction Id: {}, " + + "Message counts - Received: {}, Errors: {}, Terminated Early: {}, Abated: {}, Alerts: {}", + auditLogSpec, requestId, transactionId, + Integer.toString(tcaExecutionContexts.size()), Integer.toString(errorExecutionContexts.size()), + Integer.toString(earlyTerminationExecutionContexts.size()), + Integer.toString(abatedExecutionContexts.size()), Integer.toString(tcaAlerts.size())); + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/integration/TcaPublisherResponseHandler.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/integration/TcaPublisherResponseHandler.java new file mode 100644 index 0000000..0e81a28 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/integration/TcaPublisherResponseHandler.java @@ -0,0 +1,101 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.integration; + + +import static org.onap.dcae.analytics.model.AnalyticsHttpConstants.REQUEST_BEGIN_TS_HEADER_KEY; +import static org.onap.dcae.analytics.model.AnalyticsHttpConstants.REQUEST_END_TS_HEADER_KEY; + +import java.util.Date; +import java.util.Map; + +import org.onap.dcae.analytics.model.ecomplogger.AnalyticsErrorType; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.tca.web.util.TcaUtils; +import org.onap.dcae.analytics.web.util.AnalyticsHttpUtils; +import org.onap.dcae.utils.eelf.logger.api.info.ResponseLogInfo; +import org.onap.dcae.utils.eelf.logger.api.log.EELFLogFactory; +import org.onap.dcae.utils.eelf.logger.api.log.EELFLogger; +import org.onap.dcae.utils.eelf.logger.model.info.RequestIdLogInfoImpl; +import org.onap.dcae.utils.eelf.logger.model.info.RequestTimingLogInfoImpl; +import org.onap.dcae.utils.eelf.logger.model.info.ResponseLogInfoImpl; +import org.onap.dcae.utils.eelf.logger.model.spec.AuditLogSpecImpl; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.integration.handler.GenericHandler; +import org.springframework.messaging.MessageHeaders; + +/** + * TCA Publisher Response Handler is used to do logging of response received from DMaaP MR Publisher. It does not do + * any changes to payload or headers + * + * @author Rajiv Singla + */ +public class TcaPublisherResponseHandler implements GenericHandler<String> { + + private static final EELFLogger ECOMP_LOGGER = EELFLogFactory.getLogger(TcaPublisherResponseHandler.class); + private static final Logger logger = LoggerFactory.getLogger(TcaPublisherResponseHandler.class); + + private final TcaAppProperties tcaAppProperties; + + public TcaPublisherResponseHandler(final TcaAppProperties tcaAppProperties) { + this.tcaAppProperties = tcaAppProperties; + } + + @Override + public Object handle(final String payload, final Map<String, Object> headers) { + + final MessageHeaders messageHeaders = new MessageHeaders(headers); + final String requestId = AnalyticsHttpUtils.getRequestId(messageHeaders); + final String transactionId = AnalyticsHttpUtils.getTransactionId(messageHeaders); + final Date beginTimestamp = AnalyticsHttpUtils.getTimestampFromHeaders(headers, REQUEST_BEGIN_TS_HEADER_KEY); + final Date endTimestamp = AnalyticsHttpUtils.getTimestampFromHeaders(headers, REQUEST_END_TS_HEADER_KEY); + + if (tcaAppProperties.getTca().getEnableEcompLogging()) { + createAuditLog(requestId, transactionId, beginTimestamp, endTimestamp, payload); + } else { + logger.info("Request Id: {}, Transaction Id: {}, Transaction completion Time: {} ms, " + + "DMaaP MR Publisher Response: {}", requestId, transactionId, + endTimestamp.getTime() - beginTimestamp.getTime(), payload); + } + return payload; + + } + + private static void createAuditLog(final String requestId, + final String transactionId, + final Date requestBeginTimestamp, + final Date requestEndTimestamp, + final String tcaPublisherResponse) { + final RequestIdLogInfoImpl requestIdLogInfo = new RequestIdLogInfoImpl(requestId); + final long elapsedTime = requestEndTimestamp.getTime() - requestBeginTimestamp.getTime(); + final RequestTimingLogInfoImpl requestTimingLogInfo = new RequestTimingLogInfoImpl(requestBeginTimestamp, + requestEndTimestamp, elapsedTime); + final ResponseLogInfo responseLogInfo = + new ResponseLogInfoImpl(AnalyticsErrorType.SUCCESSFUL.getErrorCode(), + AnalyticsErrorType.SUCCESSFUL.getErrorDescription()); + final AuditLogSpecImpl auditLogSpec = new AuditLogSpecImpl(requestIdLogInfo, TcaUtils.TCA_SERVICE_LOG_INFO, + requestTimingLogInfo, responseLogInfo); + ECOMP_LOGGER.auditLog().info("Request Id: {}, Transaction Id: {}, " + + "Transaction completion Time: {} ms, DMaaP MR Publisher Response: {}", + auditLogSpec, requestId, transactionId, Long.toString(elapsedTime), tcaPublisherResponse); + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/service/TcaProcessingService.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/service/TcaProcessingService.java new file mode 100644 index 0000000..39a985c --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/service/TcaProcessingService.java @@ -0,0 +1,49 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.service; + +import java.util.List; + +import org.onap.dcae.analytics.tca.core.service.TcaExecutionContext; +import org.onap.dcae.analytics.tca.model.policy.TcaPolicy; + +/** + * Provides TCA functionality + * + * @author Rajiv Singla + */ +public interface TcaProcessingService { + + /** + * Apply policy thresholds to CEF messages and generate TCA execution results + * + * @param requestId request id associated with tca execution request + * @param transactionId transaction id associated with the tca execution request + * @param tcaPolicy tca policy that needs to be applied to CEF messages + * @param cefMessages list of CEF messages that needs to be processed by TCA + * + * @return results of TCA Processing + */ + List<TcaExecutionContext> getTcaExecutionResults(String requestId, String transactionId, + TcaPolicy tcaPolicy, + List<String> cefMessages); + + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/service/TcaProcessingServiceImpl.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/service/TcaProcessingServiceImpl.java new file mode 100644 index 0000000..3bb742a --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/service/TcaProcessingServiceImpl.java @@ -0,0 +1,87 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.service; + +import static org.onap.dcae.analytics.web.util.AnalyticsWebUtils.RANDOM_ID_SUPPLIER; +import static org.onap.dcae.analytics.web.util.AnalyticsWebUtils.REQUEST_ID_SUPPLIER; +import static org.onap.dcae.analytics.web.util.ValidationUtils.isPresent; + +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.onap.dcae.analytics.model.AnalyticsModelConstants; +import org.onap.dcae.analytics.tca.core.service.GenericTcaExecutionContext; +import org.onap.dcae.analytics.tca.core.service.GenericTcaProcessingContext; +import org.onap.dcae.analytics.tca.core.service.GenericTcaResultContext; +import org.onap.dcae.analytics.tca.core.service.TcaAaiEnrichmentContext; +import org.onap.dcae.analytics.tca.core.service.TcaAbatementContext; +import org.onap.dcae.analytics.tca.core.service.TcaExecutionContext; +import org.onap.dcae.analytics.tca.core.util.function.calculation.TcaCalculator; +import org.onap.dcae.analytics.tca.model.policy.TcaPolicy; +import org.onap.dcae.analytics.tca.web.util.TcaUtils; + +/** + * @author Rajiv Singla + */ +public class TcaProcessingServiceImpl implements TcaProcessingService { + + private final TcaAbatementContext tcaAbatementContext; + private final TcaAaiEnrichmentContext tcaAaiEnrichmentContext; + + public TcaProcessingServiceImpl(final TcaAbatementContext tcaAbatementContext, + final TcaAaiEnrichmentContext tcaAaiEnrichmentContext) { + this.tcaAbatementContext = tcaAbatementContext; + this.tcaAaiEnrichmentContext = tcaAaiEnrichmentContext; + } + + + @Override + public List<TcaExecutionContext> getTcaExecutionResults(final String requestId, + final String transactionId, + final TcaPolicy tcaPolicy, + final List<String> cefMessages) { + // create tca policy deep copy as it should be same for current execution + final TcaPolicy tcaPolicyDeepCopy = TcaUtils.getTcaPolicyDeepCopy(tcaPolicy); + // create new request id if not present + final String executionRequestId = isPresent(requestId) ? requestId : REQUEST_ID_SUPPLIER.get(); + // create transaction id if not present + final String executionTransactionId = isPresent(transactionId) ? transactionId : RANDOM_ID_SUPPLIER.get(); + + return IntStream.range(0, cefMessages.size()) + // generate initial Processing contexts + .mapToObj(cefMessageIndex -> GenericTcaExecutionContext.builder() + .requestId(executionRequestId + + AnalyticsModelConstants.ANALYTICS_REQUEST_ID_DELIMITER + cefMessageIndex) + .transactionId(executionTransactionId) + .messageIndex(cefMessageIndex) + .cefMessage(cefMessages.get(cefMessageIndex)) + .tcaPolicy(tcaPolicyDeepCopy) + .tcaProcessingContext(new GenericTcaProcessingContext()) + .tcaAbatementContext(tcaAbatementContext) + .tcaAaiEnrichmentContext(tcaAaiEnrichmentContext) + .tcaResultContext(new GenericTcaResultContext()) + .build()) + // apply tca calculator + .map(new TcaCalculator()) + // return result + .collect(Collectors.toList()); + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/TcaUtils.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/TcaUtils.java new file mode 100644 index 0000000..6744cee --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/TcaUtils.java @@ -0,0 +1,92 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.util; + +import static org.onap.dcae.analytics.tca.model.util.json.TcaModelJsonConversion.TCA_OBJECT_MAPPER; + +import com.fasterxml.jackson.core.JsonProcessingException; + +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.onap.dcae.analytics.model.TcaModelConstants; +import org.onap.dcae.analytics.model.cef.EventListener; +import org.onap.dcae.analytics.tca.model.policy.TcaPolicy; +import org.onap.dcae.analytics.web.exception.AnalyticsParsingException; +import org.onap.dcae.utils.eelf.logger.model.info.ServiceLogInfoImpl; + +/** + * @author Rajiv Singla + */ +public abstract class TcaUtils { + + /** + * TCA Service Log Info for ECOMP Logging + */ + public static final ServiceLogInfoImpl TCA_SERVICE_LOG_INFO = + new ServiceLogInfoImpl(TcaModelConstants.TCA_SERVICE_NAME, System.getProperty("user.name"), ""); + + /** + * Creates a deep copy of Tca Policy + * + * @param tcaPolicy source tca policy object + * + * @return deep copy of provided tca policy + */ + public static TcaPolicy getTcaPolicyDeepCopy(final TcaPolicy tcaPolicy) { + if (tcaPolicy != null) { + try { + return TCA_OBJECT_MAPPER.treeToValue(TCA_OBJECT_MAPPER.valueToTree(tcaPolicy), TcaPolicy.class); + } catch (JsonProcessingException e) { + throw new AnalyticsParsingException("Unable to create deep copy of TCA Policy: " + tcaPolicy, e); + } + } else { + final String errorMessage = "Invalid application state. TCA Policy must not be null"; + throw new AnalyticsParsingException(errorMessage, new IllegalStateException(errorMessage)); + } + } + + + /** + * Converts given event Listeners to list of CEF Message String + * + * @param eventListeners event listeners object + * + * @return cef messages as string + */ + public static List<String> getCefMessagesFromEventListeners(final List<EventListener> eventListeners) { + if (!Optional.ofNullable(eventListeners).isPresent()) { + return Collections.emptyList(); + } + return eventListeners.stream().map(eventListener -> { + try { + return TCA_OBJECT_MAPPER.writeValueAsString(eventListener); + } catch (JsonProcessingException e) { + throw new AnalyticsParsingException("Unable to parse EventLister to String: " + eventListener, e); + } + }).collect(Collectors.toList()); + } + + private TcaUtils() { + // private constructor + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/function/TcaAppPropsToAaiRestClientPrefsFunction.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/function/TcaAppPropsToAaiRestClientPrefsFunction.java new file mode 100644 index 0000000..759d5dd --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/function/TcaAppPropsToAaiRestClientPrefsFunction.java @@ -0,0 +1,61 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.util.function; + +import java.util.Optional; +import java.util.function.Function; + +import org.onap.dcae.analytics.model.util.function.StringToURLFunction; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.tca.web.aai.TcaAaiRestClientPreferences; +import org.onap.dcae.analytics.web.util.AnalyticsHttpUtils; +import org.springframework.http.HttpHeaders; + +/** + * @author Rajiv Singla + */ +public class TcaAppPropsToAaiRestClientPrefsFunction implements Function<TcaAppProperties, + TcaAaiRestClientPreferences> { + + @Override + public TcaAaiRestClientPreferences apply(final TcaAppProperties tcaAppProperties) { + + final TcaAppProperties.Aai aai = tcaAppProperties.getTca().getAai(); + + // if aai enrichment is not enabled no need to configure aai Rest client template + if (!tcaAppProperties.getTca().getAai().getEnableEnrichment()) { + return null; + } + + final HttpHeaders aaiHeaders = AnalyticsHttpUtils.createDefaultHttpHeaders(); + aaiHeaders.add("Real-Time", "true"); + + return new TcaAaiRestClientPreferences( + tcaAppProperties.getTca().getAai().getUrl(), + "aai-rest-client", + aaiHeaders, + aai.getUsername(), + aai.getPassword(), + Optional.ofNullable(aai.getProxyUrl()).flatMap(new StringToURLFunction()).orElse(null), + aai.getIgnoreSSLValidation(), + tcaAppProperties.getTca().getEnableEcompLogging() + ); + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/function/TcaAppPropsToMrPublisherPrefsFunction.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/function/TcaAppPropsToMrPublisherPrefsFunction.java new file mode 100644 index 0000000..fbdbac4 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/function/TcaAppPropsToMrPublisherPrefsFunction.java @@ -0,0 +1,83 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.util.function; + +import java.net.URL; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.onap.dcae.analytics.model.configbindingservice.BaseConfigBindingServiceProperties.PublisherDetails; +import org.onap.dcae.analytics.model.configbindingservice.ConfigBindingServiceConstants; +import org.onap.dcae.analytics.model.util.function.StringToURLFunction; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.web.dmaap.MrPublisherPreferences; +import org.onap.dcae.analytics.web.util.AnalyticsHttpUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; + +/** + * @author Rajiv Singla + */ +public class TcaAppPropsToMrPublisherPrefsFunction implements Function<TcaAppProperties, MrPublisherPreferences> { + + private static final Logger logger = LoggerFactory.getLogger(TcaAppPropsToMrPublisherPrefsFunction.class); + + @Override + public MrPublisherPreferences apply(final TcaAppProperties tcaAppProperties) { + + final Map<String, PublisherDetails> streamsPublishes = tcaAppProperties.getStreamsPublishes(); + + final List<Map.Entry<String, PublisherDetails>> messageRouterPublishes = + streamsPublishes.entrySet().stream() + .filter(ConfigBindingServiceConstants.MESSAGE_ROUTER_PREDICATE) + .collect(Collectors.toList()); + + // Use first publisher properties + final Map.Entry<String, PublisherDetails> firstPublisherProperties = messageRouterPublishes.get(0); + + if (messageRouterPublishes.size() > 1) { + logger.warn("Expected only one DMaaP MR publisher properties but found: {}.", streamsPublishes.size()); + } + + final String publisherPropertiesKey = firstPublisherProperties.getKey(); + final PublisherDetails publisherDetails = firstPublisherProperties.getValue(); + + logger.info("Creating DMaaP MR Publisher from config properties key: {}, props: {}", + publisherPropertiesKey, publisherDetails); + + final String requestURL = publisherDetails.getDmaapInfo().getTopicUrl(); + final HttpHeaders httpHeaders = AnalyticsHttpUtils.createDefaultHttpHeaders(); + final String username = publisherDetails.getAafUsername(); + final String password = publisherDetails.getAafPassword(); + + final URL proxyUrl = Optional.ofNullable(publisherDetails.getProxyUrl()) + .flatMap(new StringToURLFunction()).orElse(null); + + final Boolean ignoreSSLValidation = publisherDetails.getIgnoreSSLValidation(); + + return new MrPublisherPreferences(requestURL, publisherPropertiesKey, httpHeaders, username, password, + proxyUrl, ignoreSSLValidation, tcaAppProperties.getTca().getEnableEcompLogging()); + + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/function/TcaAppPropsToMrSubscriberPrefsFunction.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/function/TcaAppPropsToMrSubscriberPrefsFunction.java new file mode 100644 index 0000000..14e06a1 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/util/function/TcaAppPropsToMrSubscriberPrefsFunction.java @@ -0,0 +1,115 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.util.function; + +import java.net.URL; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.onap.dcae.analytics.model.configbindingservice.BaseConfigBindingServiceProperties.AutoAdjusting; +import org.onap.dcae.analytics.model.configbindingservice.BaseConfigBindingServiceProperties.SubscriberDetails; +import org.onap.dcae.analytics.model.configbindingservice.ConfigBindingServiceConstants; +import org.onap.dcae.analytics.model.util.function.StringToURLFunction; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.web.dmaap.MrSubscriberPollingPreferences; +import org.onap.dcae.analytics.web.dmaap.MrSubscriberPreferences; +import org.onap.dcae.analytics.web.util.AnalyticsHttpUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.http.HttpHeaders; + +/** + * @author Rajiv Singla + */ +public class TcaAppPropsToMrSubscriberPrefsFunction implements Function<TcaAppProperties, MrSubscriberPreferences> { + + private static final Logger logger = LoggerFactory.getLogger(TcaAppPropsToMrSubscriberPrefsFunction.class); + + @Override + public MrSubscriberPreferences apply(final TcaAppProperties tcaAppProperties) { + + final Map<String, SubscriberDetails> streamsSubscribes = tcaAppProperties.getStreamsSubscribes(); + + final List<Map.Entry<String, SubscriberDetails>> messageRouterSubscribers = + streamsSubscribes.entrySet().stream() + .filter(ConfigBindingServiceConstants.MESSAGE_ROUTER_PREDICATE) + .collect(Collectors.toList()); + + // Use first subscriber properties + final Map.Entry<String, SubscriberDetails> firstSubscriberProperties = messageRouterSubscribers.get(0); + + if (messageRouterSubscribers.size() > 1) { + logger.warn("Expected one DMaaP MR subscriber properties but found: {}.", messageRouterSubscribers.size()); + } + + final String subscriberPropertiesKey = firstSubscriberProperties.getKey(); + final SubscriberDetails subscriberDetails = firstSubscriberProperties.getValue(); + + logger.info("Creating DMaaP MR Subscriber from config properties key: {}, props: {}", + subscriberPropertiesKey, subscriberDetails); + + final String requestURL = subscriberDetails.getDmaapInfo().getTopicUrl(); + final HttpHeaders httpHeaders = AnalyticsHttpUtils.createDefaultHttpHeaders(); + final String username = subscriberDetails.getAafUsername(); + final String password = subscriberDetails.getAafPassword(); + final URL proxyUrl = Optional.ofNullable(subscriberDetails.getProxyUrl()) + .flatMap(new StringToURLFunction()).orElse(null); + final Boolean ignoreSSLValidation = subscriberDetails.getIgnoreSSLValidation(); + + final String consumerGroup = subscriberDetails.getConsumerGroup(); + final List<String> consumerIds = subscriberDetails.getConsumerIds(); + final Integer messageLimit = subscriberDetails.getMessageLimit(); + final Integer timeout = subscriberDetails.getTimeout(); + + final Boolean enableEcompLogging = tcaAppProperties.getTca().getEnableEcompLogging(); + + if (subscriberDetails.getPolling() == null) { + + return new MrSubscriberPreferences(requestURL, subscriberPropertiesKey, httpHeaders, username, password, + proxyUrl, ignoreSSLValidation, enableEcompLogging, consumerGroup, consumerIds, messageLimit, + timeout, null); + } + + final Integer fixedRate = subscriberDetails.getPolling().getFixedRate(); + + if (fixedRate != null && fixedRate != 0) { + logger.info("Fixed Rate polling will be used for DMaaP MR Subscriber: {}", subscriberPropertiesKey); + final MrSubscriberPollingPreferences pollingPreferences = + new MrSubscriberPollingPreferences(fixedRate, 0, fixedRate, 0); + return new MrSubscriberPreferences(requestURL, subscriberPropertiesKey, httpHeaders, username, password, + proxyUrl, ignoreSSLValidation, enableEcompLogging, consumerGroup, consumerIds, messageLimit, + timeout, pollingPreferences); + } + + final AutoAdjusting autoAdjusting = subscriberDetails.getPolling().getAutoAdjusting(); + logger.info("Selecting Auto Adjusting polling rate for DMaaP MR Subscriber: {}", subscriberPropertiesKey); + + final MrSubscriberPollingPreferences pollingPreferences = + new MrSubscriberPollingPreferences(autoAdjusting.getMin(), autoAdjusting.getStepUp(), + autoAdjusting.getMax(), autoAdjusting.getStepDown()); + return new MrSubscriberPreferences(requestURL, subscriberPropertiesKey, httpHeaders, username, password, + proxyUrl, ignoreSSLValidation, enableEcompLogging, consumerGroup, consumerIds, messageLimit, timeout, + pollingPreferences); + + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/validation/ConfigPropertiesAaiValidator.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/validation/ConfigPropertiesAaiValidator.java new file mode 100644 index 0000000..5b04e92 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/validation/ConfigPropertiesAaiValidator.java @@ -0,0 +1,88 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.validation; + + +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.onap.dcae.analytics.web.util.ValidationUtils; +import org.onap.dcae.analytics.web.validation.AnalyticsValidator; +import org.onap.dcae.analytics.web.validation.GenericValidationResponse; +import org.springframework.lang.Nullable; +import org.springframework.validation.Errors; + +/** + * @author Rajiv Singla + */ +public class ConfigPropertiesAaiValidator implements + AnalyticsValidator<TcaAppProperties.Aai, GenericValidationResponse> { + + private static final long serialVersionUID = 1L; + + @Override + public GenericValidationResponse apply(final TcaAppProperties.Aai aai) { + + final GenericValidationResponse validationResponse = new GenericValidationResponse(); + + final String genericVnfPath = aai.getGenericVnfPath(); + if (ValidationUtils.isEmpty(genericVnfPath)) { + validationResponse.addErrorMessage("generic_vnf_path", "AAI Generic vnf path must be present"); + } + + final String nodeQueryPath = aai.getNodeQueryPath(); + if (ValidationUtils.isEmpty(nodeQueryPath)) { + validationResponse.addErrorMessage("node_query_path", "AAI Node Query Path must be present"); + } + + + final String url = aai.getUrl(); + if (ValidationUtils.isEmpty(url)) { + validationResponse.addErrorMessage("url", "AAI url must be present"); + } + + return validationResponse; + } + + @Override + public boolean supports(final Class<?> type) { + return type == TcaAppProperties.Aai.class; + } + + @Override + public void validate(@Nullable final Object target, final Errors errors) { + + // if aai is not present - assuming no aai enrichment is required + if (target == null) { + return; + } + final TcaAppProperties.Aai aai = (TcaAppProperties.Aai) target; + + // skip validation if aai enrichment is not enabled + if (aai.getEnableEnrichment() == null || !aai.getEnableEnrichment()) { + return; + } + + final GenericValidationResponse validationResponse = apply(aai); + + if (validationResponse.hasErrors()) { + errors.rejectValue("aai", validationResponse.getAllErrorMessage()); + } + + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/validation/TcaAppPropertiesValidator.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/validation/TcaAppPropertiesValidator.java new file mode 100644 index 0000000..4204e41 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/validation/TcaAppPropertiesValidator.java @@ -0,0 +1,186 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.validation; + + +import java.net.MalformedURLException; +import java.net.URL; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import org.onap.dcae.analytics.model.configbindingservice.BaseConfigBindingServiceProperties.PubSubCommonDetails; +import org.onap.dcae.analytics.model.configbindingservice.BaseConfigBindingServiceProperties.PublisherDetails; +import org.onap.dcae.analytics.model.configbindingservice.BaseConfigBindingServiceProperties.SubscriberDetails; +import org.onap.dcae.analytics.model.configbindingservice.ConfigBindingServiceConstants; +import org.onap.dcae.analytics.tca.web.TcaAppProperties; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.lang.Nullable; +import org.springframework.validation.Errors; +import org.springframework.validation.Validator; + +/** + * Validator for {@link TcaAppProperties}. This validator is used by spring at start up time to validate + * TCA Application properties + * + * @author Rajiv Singla + */ +public class TcaAppPropertiesValidator implements Validator { + + private static final Logger logger = LoggerFactory.getLogger(TcaAppPropertiesValidator.class); + + @Override + public boolean supports(final Class<?> type) { + return type == TcaAppProperties.class; + } + + @Override + public void validate(@Nullable final Object props, final Errors errors) { + + if (props == null) { + errors.rejectValue(ConfigBindingServiceConstants.CONFIG_BINDING_SERVICE_PROPERTIES_KEY, + "TCA App Properties are not present"); + return; + } + + final TcaAppProperties tcaAppProperties = (TcaAppProperties) props; + + logger.info("Validating TCA App Properties: {}", tcaAppProperties); + + final Map<String, PublisherDetails> streamsPublishes = tcaAppProperties.getStreamsPublishes(); + final Map<String, SubscriberDetails> streamsSubscribes = tcaAppProperties.getStreamsSubscribes(); + + // Validate that stream publishes has at least 1 publisher and subscriber + if (!validatePubSubArePresent(errors, streamsPublishes, streamsSubscribes)) { + return; + } + + // Validate that streams publishes and subscribes has at least one message router + List<? super PubSubCommonDetails> pubSubMRCommonDetails = + validatePubSubHasMRDetails(errors, streamsPublishes, streamsSubscribes); + if (pubSubMRCommonDetails.isEmpty()) { + return; + } + + //Confirm each message router has dmaap info and their url is present and valid + validateMRProperties(errors, pubSubMRCommonDetails); + + // validated aai properties + validateAAIProperties(errors, tcaAppProperties.getTca().getAai()); + + logger.info("Validation of TCA App Properties completed successfully"); + + } + + + private void validateAAIProperties(final Errors errors, final TcaAppProperties.Aai aai) { + new ConfigPropertiesAaiValidator().validate(aai, errors); + } + + private void validateMRProperties(final Errors errors, + final List<? super PubSubCommonDetails> pubSubMRCommonDetails) { + + for (Object pubSubMRCommonDetail : pubSubMRCommonDetails) { + final PubSubCommonDetails mrDetails = (PubSubCommonDetails) pubSubMRCommonDetail; + + if (mrDetails.getDmaapInfo() == null || mrDetails.getDmaapInfo().getTopicUrl() == null) { + errors.rejectValue("dmaap_info", + "dmaap_info url not present for MR configuration properties: " + mrDetails); + } + + if (mrDetails.getDmaapInfo() != null && mrDetails.getDmaapInfo().getTopicUrl() != null + && !isURLValid(mrDetails.getDmaapInfo().getTopicUrl())) { + errors.rejectValue("topic_url", + "Invalid MR Topic URL in configuration properties:" + mrDetails); + + } + + if (mrDetails.getProxyUrl() != null && !mrDetails.getProxyUrl().trim().isEmpty() + && !isURLValid(mrDetails.getProxyUrl())) { + errors.rejectValue("proxy_url", + "Invalid Proxy url in configuration properties:" + mrDetails); + } + } + + } + + private List<? super PubSubCommonDetails> validatePubSubHasMRDetails( + final Errors errors, + final Map<String, PublisherDetails> streamsPublishes, + final Map<String, SubscriberDetails> streamsSubscribes) { + + final List<Map.Entry<String, PublisherDetails>> messageRouterPublishers = + streamsPublishes.entrySet().stream() + .filter(ConfigBindingServiceConstants.MESSAGE_ROUTER_PREDICATE) + .collect(Collectors.toList()); + if (messageRouterPublishers.isEmpty()) { + errors.rejectValue("stream_publishes", + "Stream publishes must contain at least 1 message router publisher"); + } + + final List<Map.Entry<String, SubscriberDetails>> messageRouterSubscribers = + streamsSubscribes.entrySet().stream() + .filter(ConfigBindingServiceConstants.MESSAGE_ROUTER_PREDICATE) + .collect(Collectors.toList()); + if (messageRouterSubscribers.isEmpty()) { + errors.rejectValue("stream_subscribes", + "Stream subscriber must contain at least 1 message router subscriber"); + } + + // create common pub sub MR list + final List<? super PubSubCommonDetails> pubSubMRCommonDetails = new LinkedList<>(); + pubSubMRCommonDetails.addAll(messageRouterPublishers.stream() + .map(Map.Entry::getValue).collect(Collectors.toList())); + pubSubMRCommonDetails.addAll(messageRouterSubscribers.stream() + .map(Map.Entry::getValue).collect(Collectors.toList()) + ); + + return pubSubMRCommonDetails; + } + + private boolean validatePubSubArePresent(final Errors errors, + final Map<String, PublisherDetails> streamsPublishes, + final Map<String, SubscriberDetails> + streamsSubscribes) { + if (streamsPublishes.isEmpty()) { + errors.rejectValue("streams_publishes", "Streams publishes must define at least 1 publisher"); + return false; + } + if (streamsSubscribes.isEmpty()) { + errors.rejectValue("streams_subscribes", "Streams subscribes must define at least 1 subscriber"); + return false; + } + + return true; + } + + private static boolean isURLValid(final String urlString) { + try { + new URL(urlString); + return true; + } catch (MalformedURLException ex) { + return false; + } + } + + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/validation/TcaPolicyValidator.java b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/validation/TcaPolicyValidator.java new file mode 100644 index 0000000..f380699 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/java/org/onap/dcae/analytics/tca/web/validation/TcaPolicyValidator.java @@ -0,0 +1,133 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.validation; + + +import static org.onap.dcae.analytics.web.util.ValidationUtils.isEmpty; + +import java.util.List; + +import org.onap.dcae.analytics.model.cef.EventSeverity; +import org.onap.dcae.analytics.tca.model.policy.ClosedLoopEventStatus; +import org.onap.dcae.analytics.tca.model.policy.ControlLoopSchemaType; +import org.onap.dcae.analytics.tca.model.policy.Direction; +import org.onap.dcae.analytics.tca.model.policy.MetricsPerEventName; +import org.onap.dcae.analytics.tca.model.policy.TcaPolicy; +import org.onap.dcae.analytics.tca.model.policy.Threshold; +import org.onap.dcae.analytics.web.validation.AnalyticsValidator; +import org.onap.dcae.analytics.web.validation.GenericValidationResponse; +import org.springframework.lang.Nullable; +import org.springframework.validation.Errors; + + +/** + * TCA Policy Validator validates {@link TcaPolicy} + * + * @author Rajiv Singla + */ +public class TcaPolicyValidator implements AnalyticsValidator<TcaPolicy, GenericValidationResponse> { + + private static final long serialVersionUID = 1L; + + @Override + public GenericValidationResponse apply(final TcaPolicy tcaPolicy) { + + final GenericValidationResponse validationResponse = new GenericValidationResponse(); + + // validate TCA Policy must domain present + final String domain = tcaPolicy.getDomain(); + if (isEmpty(domain)) { + validationResponse.addErrorMessage("domain", "TCA Policy must have only one domain present"); + } + + // validate TCA Policy must have at lease one metrics per event name + final List<MetricsPerEventName> metricsPerEventNames = tcaPolicy.getMetricsPerEventName(); + if (metricsPerEventNames == null || metricsPerEventNames.isEmpty()) { + validationResponse + .addErrorMessage("metricsPerEventName", "TCA Policy metricsPerEventName is empty"); + return validationResponse; + } + + // validate Metrics Per Event Name + for (MetricsPerEventName metricsPerEventName : metricsPerEventNames) { + + // event name must be present + final String eventName = metricsPerEventName.getEventName(); + if (isEmpty(eventName)) { + validationResponse.addErrorMessage("eventName", + "TCA Policy eventName is not present for metricsPerEventNames:" + metricsPerEventName); + } + + // control Loop Schema type must be present + final ControlLoopSchemaType controlLoopSchemaType = metricsPerEventName.getControlLoopSchemaType(); + if (controlLoopSchemaType == null) { + validationResponse.addErrorMessage("controlLoopEventType", + "TCA Policy controlLoopSchemaType is not present for metricsPerEventNames:" + + metricsPerEventName); + } + + // must have at least 1 threshold defined + final List<Threshold> thresholds = metricsPerEventName.getThresholds(); + if (thresholds == null || thresholds.isEmpty()) { + validationResponse.addErrorMessage("thresholds", + "TCA Policy event Name must have at least one threshold. " + + "Event Name causing this validation error:" + metricsPerEventName); + } else { + // validate each threshold must have non null - fieldPath, thresholdValue, direction and severity + for (Threshold eventNameThreshold : thresholds) { + final String fieldPath = eventNameThreshold.getFieldPath(); + final Long thresholdValue = eventNameThreshold.getThresholdValue(); + final Direction direction = eventNameThreshold.getDirection(); + final EventSeverity severity = eventNameThreshold.getSeverity(); + final ClosedLoopEventStatus closedLoopEventStatus = eventNameThreshold.getClosedLoopEventStatus(); + if (isEmpty(fieldPath) || thresholdValue == null || direction == null || severity == null || + closedLoopEventStatus == null) { + validationResponse.addErrorMessage("threshold", + "TCA Policy threshold must have fieldPath,thresholdValue,direction, " + + "closedLoopEventStatus and severity defined." + + "Threshold causing this validation error:" + eventNameThreshold); + } + } + } + } + + return validationResponse; + } + + @Override + public boolean supports(final Class<?> type) { + return type == TcaPolicy.class; + } + + @Override + public void validate(@Nullable final Object target, final Errors errors) { + + if (target == null) { + errors.rejectValue("tcaPolicy", "TCA Policy must not be null"); + return; + } + + final TcaPolicy tcaPolicy = (TcaPolicy) target; + final GenericValidationResponse validationResponse = apply(tcaPolicy); + if (validationResponse.hasErrors()) { + errors.rejectValue("tca policy", validationResponse.getAllErrorMessage()); + } + } +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/application-dev.yaml b/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/application-dev.yaml new file mode 100644 index 0000000..e8f2fe8 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/application-dev.yaml @@ -0,0 +1,50 @@ +# DEV PROFILE SETTINGS +config-binding-service: + tca: + policy: "{\"domain\":\"measurementsForVfScaling\",\"metricsPerEventName\":[{\"eventName\":\"Mfvs_eNodeB_RANKPI\",\"controlLoopSchemaType\":\"VNF\",\"policyScope\":\"resource=vFirewall;type=configuration\",\"policyName\":\"configuration.dcae.microservice.tca.xml\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"CL-FRWL-LOW-TRAFFIC-SIG-d925ed73-8231-4d02-9545-db4e101f88f8\",\"closedLoopEventStatus\":\"ONSET\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated\",\"thresholdValue\":4000,\"direction\":\"LESS_OR_EQUAL\",\"severity\":\"MAJOR\"},{\"closedLoopControlName\":\"CL-FRWL-HIGH-TRAFFIC-SIG-EA36FE84-9342-5E13-A656-EC5F21309A09\",\"closedLoopEventStatus\":\"ONSET\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated\",\"thresholdValue\":20000,\"direction\":\"GREATER_OR_EQUAL\",\"severity\":\"CRITICAL\"},{\"closedLoopControlName\":\"CL-FRWL-HIGH-TRAFFIC-SIG-EA36FE84-9342-5E13-A656-EC5F21309A09\",\"closedLoopEventStatus\":\"ABATED\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated\",\"thresholdValue\":0,\"direction\":\"EQUAL\",\"severity\":\"CRITICAL\"}]},{\"eventName\":\"vLoadBalancer\",\"controlLoopSchemaType\":\"VNF\",\"policyScope\":\"resource=vLoadBalancer;type=configuration\",\"policyName\":\"configuration.dcae.microservice.tca.xml\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"CL-LBAL-LOW-TRAFFIC-SIG-FB480F95-A453-6F24-B767-FD703241AB1A\",\"closedLoopEventStatus\":\"ONSET\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated\",\"thresholdValue\":500,\"direction\":\"LESS_OR_EQUAL\",\"severity\":\"MAJOR\"},{\"closedLoopControlName\":\"CL-LBAL-LOW-TRAFFIC-SIG-0C5920A6-B564-8035-C878-0E814352BC2B\",\"closedLoopEventStatus\":\"ONSET\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated\",\"thresholdValue\":5000,\"direction\":\"GREATER_OR_EQUAL\",\"severity\":\"CRITICAL\"}]},{\"eventName\":\"virtualVMEventName\",\"controlLoopSchemaType\":\"VM\",\"policyScope\":\"resource=virtualVM;type=configuration\",\"policyName\":\"configuration.dcae.microservice.tca.xml\",\"policyVersion\":\"v0.0.1\",\"thresholds\":[{\"closedLoopControlName\":\"CL-LBAL-LOW-TRAFFIC-SIG-FB480F95-A453-6F24-B767-FD703241AB1A\",\"closedLoopEventStatus\":\"ONSET\",\"version\":\"1.0.2\",\"fieldPath\":\"$.event.measurementsForVfScalingFields.vNicPerformanceArray[*].receivedBroadcastPacketsAccumulated\",\"thresholdValue\":500,\"direction\":\"LESS_OR_EQUAL\",\"severity\":\"MAJOR\"}]}]}" + processing_batch_size: 10000 + enable_abatement: true + enable_ecomp_logging: true + aai: + enable_enrichment: true + url: "http://localhost:8443" + username: "DCAE" + password: "DCAE" + generic_vnf_path: "aai/v11/network/generic-vnfs/generic-vnf" + node_query_path: "aai/v11/search/nodes-query" + service_calls: + aai_broker_handle: + - "135.205.226.128:32768" + streams_publishes: + tca_handle_out: + type: "message_router" + aaf_username: "USER" + aaf_password: "PASSWORD" + dmaap_info: + client_role: "publisher" + client_id: "tca-pub-0" + location: "ecomp" + topic_url: "http://localhost:8080/events/PubTopic" + streams_subscribes: + tca_handle_in: + type: "message_router" + aaf_username: "USER" + aaf_password : "PASSWORD" + dmaap_info: + client_role: "subscriber" + client_id: "tca-sub-0" + location: "ecomp" + topic_url: "http://localhost:8080/events/SubTopic" + consumer_group: "cg1" + consumer_ids: + - "c0" + - "c1" + message_limit: 50000 + timeout: -1 + polling: + fixed_rate: 0 + auto_adjusting: + min: 30000 + step_up: 10000 + max: 60000 + step_down: 30000 diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/application-mongo.yaml b/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/application-mongo.yaml new file mode 100644 index 0000000..6727518 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/application-mongo.yaml @@ -0,0 +1,4 @@ +spring: + data: + mongodb: + uri: "mongodb://localhost:27017/analytics-tca" diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/application.yaml b/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/application.yaml new file mode 100644 index 0000000..1fdb070 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/application.yaml @@ -0,0 +1,53 @@ +# SPRING SETTINGS +spring: + application: + name: "dcae-analytics-tca" + main: + banner-mode: "off" + profiles: + active: dev + servlet: + multipart: + # Enable multi part file uploads / download + enabled: true + # Threshold after which files are written to disk. + file-size-threshold: 100KB + # Max file size + max-file-size: 512MB + # Max Request size + max-request-size: 600MB + output: + ansi: + enabled: always + +# ENDPOINTS +management: + endpoint: + health: + show-details: always + shutdown: + enabled: true + endpoints: + web: + exposure: + include: '*' + info: + git: + mode: full + health: + redis: + enabled: false + mongo: + enabled: false + +# SERVER +server: + port: 9091 + compression: + # Enable gzip compression of response + enabled: true + mime-types: application/json,text/plain + min-response-size: 4096 + http2: + enabled: true + diff --git a/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/bootstrap.yaml b/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/bootstrap.yaml new file mode 100644 index 0000000..b17d963 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/main/resources/config/bootstrap.yaml @@ -0,0 +1,4 @@ +spring: + cloud: + config: + enabled: false diff --git a/dcae-analytics/dcae-analytics-tca-web/src/test/java/org/onap/dcae/analytics/tca/web/BaseTcaWebSpringBootIT.java b/dcae-analytics/dcae-analytics-tca-web/src/test/java/org/onap/dcae/analytics/tca/web/BaseTcaWebSpringBootIT.java new file mode 100644 index 0000000..e331c95 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/test/java/org/onap/dcae/analytics/tca/web/BaseTcaWebSpringBootIT.java @@ -0,0 +1,54 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web; + +import org.onap.dcae.analytics.model.AnalyticsProfile; +import org.onap.dcae.analytics.tca.web.config.TcaWebTestConfig; +import org.onap.dcae.analytics.test.BaseAnalyticsSpringBootIT; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.ContextConfiguration; + +/** + * @author Rajiv Singla + */ +@ActiveProfiles({AnalyticsProfile.DEV_PROFILE_NAME}) +@ContextConfiguration(classes = {TcaWebTestConfig.class}) +public abstract class BaseTcaWebSpringBootIT extends BaseAnalyticsSpringBootIT { + + protected static final String TEST_POLICY_JSON_STRING; + protected static final String TEST_CEF_EVENT_LISTENER_STRING; + protected static final String TEST_CEF_JSON_MESSAGE_WITH_VIOLATION_STRING; + protected static final String TEST_CEF_JSON_MESSAGE_WITH_ABATEMENT_STRING; + protected static final String TEST_CEF_JSON_MESSAGE_WITH_INAPPLICABLE_EVENT_NAME; + protected static final String TEST_REQUEST_ID = "testRequestId"; + protected static final String TEST_TRANSACTION_ID = "testTransactionId"; + + static { + + TEST_POLICY_JSON_STRING = fromStream(TestFileLocation.TCA_POLICY_JSON); + TEST_CEF_EVENT_LISTENER_STRING = fromStream(TestFileLocation.CEF_JSON_MESSAGE); + TEST_CEF_JSON_MESSAGE_WITH_VIOLATION_STRING = fromStream(TestFileLocation.CEF_JSON_MESSAGE_WITH_VIOLATION); + TEST_CEF_JSON_MESSAGE_WITH_ABATEMENT_STRING = fromStream(TestFileLocation.CEF_JSON_MESSAGE_WITH_ABATEMENT); + TEST_CEF_JSON_MESSAGE_WITH_INAPPLICABLE_EVENT_NAME = fromStream(TestFileLocation + .CEF_JSON_MESSAGE_WITH_INAPPLICABLE_EVENT_NAME); + + } + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/test/java/org/onap/dcae/analytics/tca/web/config/TcaWebTestConfig.java b/dcae-analytics/dcae-analytics-tca-web/src/test/java/org/onap/dcae/analytics/tca/web/config/TcaWebTestConfig.java new file mode 100644 index 0000000..ccd5d97 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/test/java/org/onap/dcae/analytics/tca/web/config/TcaWebTestConfig.java @@ -0,0 +1,34 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.config; + +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.context.annotation.Configuration; +import org.springframework.context.annotation.Import; + +/** + * @author Rajiv Singla + */ +@Configuration +@EnableAutoConfiguration +@Import(value = {TcaWebConfig.class}) +public class TcaWebTestConfig { + +} diff --git a/dcae-analytics/dcae-analytics-tca-web/src/test/java/org/onap/dcae/analytics/tca/web/service/TcaProcessingServiceImplTest.java b/dcae-analytics/dcae-analytics-tca-web/src/test/java/org/onap/dcae/analytics/tca/web/service/TcaProcessingServiceImplTest.java new file mode 100644 index 0000000..5723160 --- /dev/null +++ b/dcae-analytics/dcae-analytics-tca-web/src/test/java/org/onap/dcae/analytics/tca/web/service/TcaProcessingServiceImplTest.java @@ -0,0 +1,72 @@ +/* + * ================================================================================ + * Copyright (c) 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.dcae.analytics.tca.web.service; + +import com.fasterxml.jackson.databind.ObjectMapper; + +import java.util.Arrays; +import java.util.List; + +import org.junit.jupiter.api.Test; +import org.onap.dcae.analytics.tca.core.service.TcaExecutionContext; +import org.onap.dcae.analytics.tca.model.facade.TcaAlert; +import org.onap.dcae.analytics.tca.web.BaseTcaWebSpringBootIT; +import org.onap.dcae.analytics.tca.web.domain.TcaPolicyWrapper; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @author Rajiv Singla + */ +class TcaProcessingServiceImplTest extends BaseTcaWebSpringBootIT { + + @Autowired + private TcaProcessingService tcaProcessingService; + + @Autowired + private TcaPolicyWrapper tcaPolicyWrapper; + + @Autowired + private ObjectMapper objectMapper; + + @Test + void getTcaExecutionResults() throws Exception { + + final List<TcaExecutionContext> tcaExecutionResults = + tcaProcessingService.getTcaExecutionResults + (TEST_REQUEST_ID, TEST_TRANSACTION_ID, tcaPolicyWrapper.getTcaPolicy(), + Arrays.asList(TEST_CEF_EVENT_LISTENER_STRING, + TEST_CEF_JSON_MESSAGE_WITH_VIOLATION_STRING, + TEST_CEF_JSON_MESSAGE_WITH_ABATEMENT_STRING, + TEST_CEF_JSON_MESSAGE_WITH_INAPPLICABLE_EVENT_NAME)); + + + for (TcaExecutionContext tcaExecutionResult : tcaExecutionResults) { + final TcaAlert tcaAlert = tcaExecutionResult.getTcaResultContext().getTcaAlert(); + String tcaAlertString = ""; + if (tcaAlert != null) { + tcaAlertString = objectMapper.writeValueAsString(tcaAlert); + } + logger.debug("{} -> {}", tcaExecutionResult.getRequestId(), tcaAlertString); + + } + + } + +} |