aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authoradheli.tavares <adheli.tavares@est.tech>2021-05-11 14:35:20 +0100
committeradheli.tavares <adheli.tavares@est.tech>2021-05-28 15:45:52 +0100
commit09e2bc57b947fb71c4dde9a8c0ded52f695abda1 (patch)
treef2259c0b5a0968792d6f3fa51bc4c9ae31ae2756
parente6bc3b407aadcab3b54074e39afc4c4dfe142b06 (diff)
Handling Policy deploy/undeploy audit models
Added a new Entity to store information when a Pdp Policy is deployed or undeployed and its create/retrieve methods. Change-Id: I35b3608c878bbfbbee0a99a124d100a48fe08131 Issue-ID: POLICY-2899 Signed-off-by: adheli.tavares <adheli.tavares@est.tech>
-rw-r--r--models-dao/src/main/java/org/onap/policy/models/dao/PfDao.java11
-rw-r--r--models-dao/src/main/java/org/onap/policy/models/dao/impl/DefaultPfDao.java35
-rw-r--r--models-dao/src/test/java/org/onap/policy/models/dao/EntityTest.java1
-rw-r--r--models-pap/pom.xml12
-rw-r--r--models-pap/src/main/java/org/onap/policy/models/pap/concepts/PolicyAudit.java50
-rw-r--r--models-pap/src/main/java/org/onap/policy/models/pap/persistence/concepts/JpaPolicyAudit.java191
-rw-r--r--models-pap/src/main/java/org/onap/policy/models/pap/persistence/provider/PolicyAuditProvider.java137
-rw-r--r--models-pap/src/test/java/org/onap/policy/models/pap/persistence/concepts/JpaPolicyAuditTest.java126
-rw-r--r--models-pap/src/test/java/org/onap/policy/models/pap/persistence/provider/PolicyAuditProviderTest.java241
-rw-r--r--models-pap/src/test/resources/META-INF/persistence.xml46
10 files changed, 842 insertions, 8 deletions
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/PfDao.java b/models-dao/src/main/java/org/onap/policy/models/dao/PfDao.java
index 844759367..378ae59b6 100644
--- a/models-dao/src/main/java/org/onap/policy/models/dao/PfDao.java
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/PfDao.java
@@ -256,6 +256,17 @@ public interface PfDao {
*
* @param <T> the type of the objects to get, a subclass of {@link PfConcept}
* @param someClass the class of the objects to get, a subclass of {@link PfConcept}
+ * @param orderBy field from class to order results by
+ * @param numRecords number of records to be retrieved
+ * @return the objects or null if no objects were retrieved
+ */
+ <T extends PfConcept> List<T> getAll(Class<T> someClass, String orderBy, Integer numRecords);
+
+ /**
+ * Get all the objects in the database of a given type.
+ *
+ * @param <T> the type of the objects to get, a subclass of {@link PfConcept}
+ * @param someClass the class of the objects to get, a subclass of {@link PfConcept}
* @param name the name of the concepts for which to get all versions
* @return the objects or null if no objects were retrieved
*/
diff --git a/models-dao/src/main/java/org/onap/policy/models/dao/impl/DefaultPfDao.java b/models-dao/src/main/java/org/onap/policy/models/dao/impl/DefaultPfDao.java
index d1e32935c..009563078 100644
--- a/models-dao/src/main/java/org/onap/policy/models/dao/impl/DefaultPfDao.java
+++ b/models-dao/src/main/java/org/onap/policy/models/dao/impl/DefaultPfDao.java
@@ -32,6 +32,7 @@ import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.TypedQuery;
import javax.ws.rs.core.Response;
+import org.apache.commons.lang3.StringUtils;
import org.onap.policy.models.base.PfConcept;
import org.onap.policy.models.base.PfConceptKey;
import org.onap.policy.models.base.PfGeneratedIdKey;
@@ -72,6 +73,7 @@ public class DefaultPfDao implements PfDao {
private static final String WHERE = " WHERE ";
private static final String AND = " AND ";
+ private static final String ORDER_BY = " ORDER BY c.";
private static final String NAME_FILTER = "c.key.name = :name";
private static final String VERSION_FILTER = "c.key.version = :version";
@@ -395,9 +397,8 @@ public class DefaultPfDao implements PfDao {
try {
PfFilter timeStampFilter = new PfFilterFactory().createFilter(someClass);
- filterQueryString = timeStampFilter.addFilter(filterQueryString,
- name, startTime, endTime, filterMap, sortOrder, getRecordNum);
-
+ filterQueryString = timeStampFilter.addFilter(filterQueryString, name, startTime, endTime, filterMap,
+ sortOrder, getRecordNum);
TypedQuery<T> query = mg.createQuery(setQueryTable(filterQueryString, someClass), someClass);
@@ -427,7 +428,7 @@ public class DefaultPfDao implements PfDao {
LOGGER.debug("filterQueryString is \"{}\"", filterQueryString);
return query.getResultList();
- } finally {
+ } finally {
mg.close();
}
}
@@ -505,6 +506,27 @@ public class DefaultPfDao implements PfDao {
}
@Override
+ public <T extends PfConcept> List<T> getAll(Class<T> someClass, String orderBy, Integer numRecords) {
+
+ if (someClass == null) {
+ return Collections.emptyList();
+ }
+ final var mg = getEntityManager();
+ try {
+ String query = setQueryTable(SELECT_FROM_TABLE, someClass);
+
+ if (StringUtils.isNotBlank(orderBy)) {
+ query = query.concat(ORDER_BY).concat(orderBy);
+ }
+
+ return mg.createQuery(query, someClass).setMaxResults(numRecords)
+ .getResultList();
+ } finally {
+ mg.close();
+ }
+ }
+
+ @Override
public <T extends PfConcept> List<T> getAllVersionsByParent(final Class<T> someClass, final String parentKeyName) {
if (someClass == null || parentKeyName == null) {
return Collections.emptyList();
@@ -539,9 +561,8 @@ public class DefaultPfDao implements PfDao {
}
@Override
- public <T extends PfConcept> List<T> getByTimestamp(final Class<T> someClass,
- final PfGeneratedIdKey key,
- final Instant timeStamp) {
+ public <T extends PfConcept> List<T> getByTimestamp(final Class<T> someClass, final PfGeneratedIdKey key,
+ final Instant timeStamp) {
if (someClass == null || key == null || timeStamp == null) {
return Collections.emptyList();
}
diff --git a/models-dao/src/test/java/org/onap/policy/models/dao/EntityTest.java b/models-dao/src/test/java/org/onap/policy/models/dao/EntityTest.java
index 66fc1b502..59fc9b482 100644
--- a/models-dao/src/test/java/org/onap/policy/models/dao/EntityTest.java
+++ b/models-dao/src/test/java/org/onap/policy/models/dao/EntityTest.java
@@ -183,6 +183,7 @@ public class EntityTest {
pfDao.get(null, nullTimeKey);
pfDao.getAll(null);
pfDao.getAll(null, nullKey);
+ pfDao.getAll(null, null, null);
pfDao.getConcept(null, nullKey);
pfDao.getConcept(PfConceptKey.class, nullKey);
pfDao.getConcept(null, nullRefKey);
diff --git a/models-pap/pom.xml b/models-pap/pom.xml
index f2ac085a7..39508638e 100644
--- a/models-pap/pom.xml
+++ b/models-pap/pom.xml
@@ -1,6 +1,6 @@
<!--
============LICENSE_START=======================================================
- Copyright (C) 2019 Nordix Foundation.
+ Copyright (C) 2019-2021 Nordix Foundation.
Copyright (C) 2020 AT&T Intellectual Property. All rights reserved.
================================================================================
Licensed under the Apache License, Version 2.0 (the "License");
@@ -53,5 +53,15 @@
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.h2database</groupId>
+ <artifactId>h2</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/models-pap/src/main/java/org/onap/policy/models/pap/concepts/PolicyAudit.java b/models-pap/src/main/java/org/onap/policy/models/pap/concepts/PolicyAudit.java
new file mode 100644
index 000000000..765d246a6
--- /dev/null
+++ b/models-pap/src/main/java/org/onap/policy/models/pap/concepts/PolicyAudit.java
@@ -0,0 +1,50 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pap.concepts;
+
+import java.time.Instant;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+/**
+ * Audit info on policy actions.
+ */
+@Data
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class PolicyAudit {
+
+ public enum AuditAction {
+ DEPLOYMENT, UNDEPLOYMENT
+ }
+
+ private Long auditId;
+ private String pdpGroup;
+ private String pdpType;
+ private ToscaConceptIdentifier policy;
+ private AuditAction action;
+ private Instant timestamp;
+ private String user;
+}
diff --git a/models-pap/src/main/java/org/onap/policy/models/pap/persistence/concepts/JpaPolicyAudit.java b/models-pap/src/main/java/org/onap/policy/models/pap/persistence/concepts/JpaPolicyAudit.java
new file mode 100644
index 000000000..b31af8ea0
--- /dev/null
+++ b/models-pap/src/main/java/org/onap/policy/models/pap/persistence/concepts/JpaPolicyAudit.java
@@ -0,0 +1,191 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pap.persistence.concepts;
+
+import java.time.Instant;
+import java.util.Date;
+import java.util.List;
+import javax.persistence.Column;
+import javax.persistence.EmbeddedId;
+import javax.persistence.Entity;
+import javax.persistence.Index;
+import javax.persistence.Inheritance;
+import javax.persistence.InheritanceType;
+import javax.persistence.Table;
+import javax.persistence.Temporal;
+import javax.persistence.TemporalType;
+import javax.validation.constraints.NotNull;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import org.apache.commons.lang3.builder.CompareToBuilder;
+import org.onap.policy.common.utils.validation.Assertions;
+import org.onap.policy.models.base.PfAuthorative;
+import org.onap.policy.models.base.PfConcept;
+import org.onap.policy.models.base.PfGeneratedIdKey;
+import org.onap.policy.models.base.PfKey;
+import org.onap.policy.models.base.PfReferenceKey;
+import org.onap.policy.models.base.validation.annotations.VerifyKey;
+import org.onap.policy.models.pap.concepts.PolicyAudit;
+import org.onap.policy.models.pap.concepts.PolicyAudit.AuditAction;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+/**
+ * Entity to keep the records on policy actions for audit.
+ *
+ * @author Adheli Tavares (adheli.tavares@est.tech)
+ *
+ */
+@Entity
+@Table(name = "JpaPolicyAudit", indexes = {@Index(name = "JpaPolicyAuditIndex_timestamp", columnList = "timeStamp")})
+@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
+@Data
+@EqualsAndHashCode(callSuper = false)
+public class JpaPolicyAudit extends PfConcept implements PfAuthorative<PolicyAudit> {
+ private static final long serialVersionUID = -2935734300607322191L;
+
+ @EmbeddedId
+ @Column
+ @NotNull
+ @VerifyKey(versionNotNull = true)
+ private PfGeneratedIdKey key;
+
+ @Column
+ private String pdpGroup;
+
+ @Column
+ private String pdpType;
+
+ @Column
+ @NotNull
+ private AuditAction action;
+
+ @Column
+ @Temporal(TemporalType.TIMESTAMP)
+ @NotNull
+ private Date timeStamp;
+
+ @Column
+ private String user;
+
+ /**
+ * Default constructor.
+ */
+ public JpaPolicyAudit() {
+ key = new PfGeneratedIdKey();
+ }
+
+ /**
+ * Constructor from an authorative.
+ *
+ * @param audit authorative model
+ */
+ public JpaPolicyAudit(PolicyAudit audit) {
+ fromAuthorative(audit);
+ }
+
+ /**
+ * Constructor as a copy.
+ *
+ * @param copyConcept original entity to be copied
+ */
+ public JpaPolicyAudit(JpaPolicyAudit copyConcept) {
+ this.key = new PfGeneratedIdKey(copyConcept.getKey());
+ this.pdpGroup = copyConcept.getPdpGroup();
+ this.pdpType = copyConcept.getPdpType();
+ this.action = copyConcept.getAction();
+ this.timeStamp = copyConcept.getTimeStamp();
+ this.user = copyConcept.getUser();
+ }
+
+ @Override
+ public int compareTo(PfConcept o) {
+ if (o == null) {
+ return -1;
+ }
+ if (this == o) {
+ return 0;
+ }
+ if (getClass() != o.getClass()) {
+ return getClass().getName().compareTo(o.getClass().getName());
+ }
+
+ final JpaPolicyAudit other = (JpaPolicyAudit) o;
+
+ // @formatter:off
+ return new CompareToBuilder()
+ .append(key, other.key)
+ .append(pdpGroup, other.pdpGroup)
+ .append(pdpType, other.pdpType)
+ .append(action, other.action)
+ .append(timeStamp, other.timeStamp)
+ .append(user, other.user)
+ .toComparison();
+ // @formatter:on
+ }
+
+ @Override
+ public PolicyAudit toAuthorative() {
+ ToscaConceptIdentifier policyIdent = new ToscaConceptIdentifier(key.getName(), key.getVersion());
+
+ // @formatter:off
+ return PolicyAudit.builder()
+ .auditId(key.getGeneratedId())
+ .pdpGroup(pdpGroup)
+ .pdpType(pdpType)
+ .policy(policyIdent)
+ .action(action)
+ .timestamp(timeStamp == null ? null : timeStamp.toInstant())
+ .user(user)
+ .build();
+ // @formatter:on
+ }
+
+ @Override
+ public void fromAuthorative(PolicyAudit authorativeConcept) {
+ if (authorativeConcept.getPolicy() != null) {
+ final ToscaConceptIdentifier policy = authorativeConcept.getPolicy();
+ key = new PfGeneratedIdKey(policy.getName(), policy.getVersion(), authorativeConcept.getAuditId());
+ } else {
+ key = new PfGeneratedIdKey();
+ }
+
+ pdpGroup = authorativeConcept.getPdpGroup();
+ pdpType = authorativeConcept.getPdpType();
+ action = authorativeConcept.getAction();
+ timeStamp = authorativeConcept.getTimestamp() == null ? Date.from(Instant.now())
+ : Date.from(authorativeConcept.getTimestamp());
+ user = authorativeConcept.getUser();
+ }
+
+ @Override
+ public List<PfKey> getKeys() {
+ return getKey().getKeys();
+ }
+
+ @Override
+ public void clean() {
+ key.clean();
+
+ pdpGroup = Assertions.validateStringParameter("pdpGroup", pdpGroup, PfReferenceKey.LOCAL_NAME_REGEXP);
+ pdpType = Assertions.validateStringParameter("pdpType", pdpType, PfReferenceKey.LOCAL_NAME_REGEXP);
+ user = Assertions.validateStringParameter("user", user, PfReferenceKey.LOCAL_NAME_REGEXP);
+ }
+}
diff --git a/models-pap/src/main/java/org/onap/policy/models/pap/persistence/provider/PolicyAuditProvider.java b/models-pap/src/main/java/org/onap/policy/models/pap/persistence/provider/PolicyAuditProvider.java
new file mode 100644
index 000000000..c117beefa
--- /dev/null
+++ b/models-pap/src/main/java/org/onap/policy/models/pap/persistence/provider/PolicyAuditProvider.java
@@ -0,0 +1,137 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pap.persistence.provider;
+
+import java.time.Instant;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import javax.ws.rs.core.Response;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NonNull;
+import org.apache.commons.lang3.StringUtils;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.onap.policy.models.dao.PfDao;
+import org.onap.policy.models.pap.concepts.PolicyAudit;
+import org.onap.policy.models.pap.concepts.PolicyAudit.AuditAction;
+import org.onap.policy.models.pap.persistence.concepts.JpaPolicyAudit;
+
+/**
+ * Provider for Policy Audit.
+ *
+ * @author Adheli Tavares (adheli.tavares@est.tech)
+ *
+ */
+public class PolicyAuditProvider {
+
+ private static final Integer DEFAULT_MAX_RECORDS = 100;
+ private static final String DESCENDING_ORDER = "DESC";
+
+ /**
+ * Create audit records.
+ *
+ * @param audits list of policy audit
+ */
+ public void createAuditRecords(@NonNull PfDao dao, @NonNull final List<PolicyAudit> audits) {
+ List<JpaPolicyAudit> jpaAudits = audits.stream().map(JpaPolicyAudit::new).collect(Collectors.toList());
+
+ BeanValidationResult result = new BeanValidationResult("createAuditRecords", jpaAudits);
+
+ int count = 0;
+ for (JpaPolicyAudit jpaAudit: jpaAudits) {
+ result.addResult(jpaAudit.validate(String.valueOf(count++)));
+ }
+
+ if (!result.isValid()) {
+ throw new PfModelRuntimeException(Response.Status.BAD_REQUEST, result.getResult());
+ }
+
+ dao.createCollection(jpaAudits);
+ }
+
+ /**
+ * Collect all audit records.
+ *
+ * @param numRecords number of records to be collected
+ * @return list of {@link PolicyAudit} records
+ */
+ public List<PolicyAudit> getAuditRecords(@NonNull PfDao dao, @NonNull Integer numRecords) {
+ numRecords = numRecords > DEFAULT_MAX_RECORDS ? DEFAULT_MAX_RECORDS : numRecords;
+
+ // @formatter:off
+ return dao.getAll(JpaPolicyAudit.class, "timeStamp DESC", numRecords)
+ .stream()
+ .map(JpaPolicyAudit::toAuthorative)
+ .collect(Collectors.toList());
+ // @formatter:on
+ }
+
+ /**
+ * Collect audit records based on filters at {@link AuditFilter}.
+ *
+ * @param auditFilter {@link AuditFilter} object with filters for search
+ * @param numRecords number of records to be collected
+ * @return list of {@link PolicyAudit} records
+ */
+ public List<PolicyAudit> getAuditRecords(@NonNull PfDao dao, @NonNull AuditFilter auditFilter,
+ @NonNull Integer numRecords) {
+ numRecords = numRecords > DEFAULT_MAX_RECORDS ? DEFAULT_MAX_RECORDS : numRecords;
+
+ Map<String, Object> filter = new HashMap<>();
+ if (StringUtils.isNotBlank(auditFilter.getPdpGroup())) {
+ filter.put("pdpGroup", auditFilter.getPdpGroup());
+ }
+
+ if (auditFilter.getAction() != null) {
+ filter.put("action", auditFilter.getAction());
+ }
+
+ // @formatter:off
+ return dao.getFiltered(JpaPolicyAudit.class,
+ auditFilter.getName(), auditFilter.getVersion(),
+ auditFilter.getFromDate(), auditFilter.getToDate(),
+ filter, DESCENDING_ORDER, numRecords)
+ .stream().map(JpaPolicyAudit::toAuthorative).collect(Collectors.toList());
+ // @formatter:on
+ }
+
+ /**
+ * Create a filter for looking for audit records.
+ * name - policy name
+ * version - policy version
+ * pdpGroup - PDP group that policy might be related
+ * action - type of action/operation realized on policy
+ * fromDate - start of period in case of time interval search
+ */
+ @Data
+ @Builder
+ protected static class AuditFilter {
+ private String name;
+ private String version;
+ private AuditAction action;
+ private String pdpGroup;
+ private Instant fromDate;
+ private Instant toDate;
+ }
+}
diff --git a/models-pap/src/test/java/org/onap/policy/models/pap/persistence/concepts/JpaPolicyAuditTest.java b/models-pap/src/test/java/org/onap/policy/models/pap/persistence/concepts/JpaPolicyAuditTest.java
new file mode 100644
index 000000000..4f8693304
--- /dev/null
+++ b/models-pap/src/test/java/org/onap/policy/models/pap/persistence/concepts/JpaPolicyAuditTest.java
@@ -0,0 +1,126 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pap.persistence.concepts;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatNoException;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.common.parameters.BeanValidationResult;
+import org.onap.policy.models.pap.concepts.PolicyAudit;
+import org.onap.policy.models.pap.concepts.PolicyAudit.AuditAction;
+import org.onap.policy.models.pdp.concepts.PdpPolicyStatus;
+import org.onap.policy.models.pdp.concepts.PdpPolicyStatus.State;
+import org.onap.policy.models.pdp.persistence.concepts.JpaPdpPolicyStatus;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+public class JpaPolicyAuditTest {
+
+ private static final ToscaConceptIdentifier MY_POLICY = new ToscaConceptIdentifier("MyPolicy", "1.2.3");
+ private static final String PDP_GROUP = "pdpGroupxyz";
+ private static final String USER = "user";
+
+ PolicyAudit audit;
+
+ /**
+ * Setup an audit for usage on unit tests.
+ */
+ @Before
+ public void setup() {
+ audit = PolicyAudit.builder().auditId(1L).pdpGroup(PDP_GROUP).pdpType("pdpType").policy(MY_POLICY)
+ .action(AuditAction.DEPLOYMENT).timestamp(Instant.now().truncatedTo(ChronoUnit.SECONDS)).build();
+ }
+
+ @Test
+ public void testCompareTo() {
+ JpaPolicyAudit jpaAudit = new JpaPolicyAudit(audit);
+ assertEquals(-1, jpaAudit.compareTo(null));
+ assertEquals(0, jpaAudit.compareTo(jpaAudit));
+ assertEquals(0, jpaAudit.compareTo(new JpaPolicyAudit(jpaAudit)));
+
+ PdpPolicyStatus idw = PdpPolicyStatus.builder().deploy(true).state(State.SUCCESS).pdpGroup(PDP_GROUP)
+ .pdpId("wId").policy(MY_POLICY).policyType(MY_POLICY).build();
+ JpaPdpPolicyStatus jpaStatus = new JpaPdpPolicyStatus(idw);
+ assertNotEquals(0, jpaAudit.compareTo(jpaStatus));
+ }
+
+ @Test
+ public void testKeys() {
+ JpaPolicyAudit jpaAudit = new JpaPolicyAudit();
+ assertThat(jpaAudit.getKeys()).isNotNull();
+ assertTrue(jpaAudit.getKey().isNullKey());
+
+ jpaAudit = new JpaPolicyAudit(audit);
+ assertFalse(jpaAudit.getKey().isNullKey());
+ }
+
+ @Test
+ public void testClean() {
+ audit.setUser(" user");
+ JpaPolicyAudit jpaAudit = new JpaPolicyAudit(audit);
+ assertThatNoException().isThrownBy(() -> jpaAudit.clean());
+ assertEquals(USER, jpaAudit.getUser());
+ }
+
+ @Test
+ public void testToAuthorative() {
+ audit.setUser(USER);
+ JpaPolicyAudit jpaAudit = new JpaPolicyAudit(audit);
+ PolicyAudit convertedAudit = jpaAudit.toAuthorative();
+
+ assertEquals(audit, convertedAudit);
+ assertEquals(USER, convertedAudit.getUser());
+
+ JpaPolicyAudit jpaAuditWithNullKey = new JpaPolicyAudit();
+ PolicyAudit convertedAudit2 = jpaAuditWithNullKey.toAuthorative();
+ assertTrue(convertedAudit2.getPolicy().asConceptKey().isNullKey());
+
+ }
+
+ @Test
+ public void testConversionsWithRequiredOnly() {
+ audit = PolicyAudit.builder().policy(MY_POLICY).action(AuditAction.DEPLOYMENT)
+ .timestamp(Instant.now().truncatedTo(ChronoUnit.SECONDS)).build();
+
+ JpaPolicyAudit jpaAudit = new JpaPolicyAudit(audit);
+ PolicyAudit convertedAudit = jpaAudit.toAuthorative();
+
+ assertEquals(audit, convertedAudit);
+ assertTrue(jpaAudit.validate("jpaAudit").isValid());
+ }
+
+ @Test
+ public void testValidation() {
+ PolicyAudit invalidAudit = PolicyAudit.builder().pdpGroup(PDP_GROUP).user(USER).build();
+
+ JpaPolicyAudit jpaAudit = new JpaPolicyAudit(invalidAudit);
+
+ BeanValidationResult result = jpaAudit.validate("jpaAudit");
+ assertFalse(result.isValid());
+ }
+}
diff --git a/models-pap/src/test/java/org/onap/policy/models/pap/persistence/provider/PolicyAuditProviderTest.java b/models-pap/src/test/java/org/onap/policy/models/pap/persistence/provider/PolicyAuditProviderTest.java
new file mode 100644
index 000000000..da231dc7b
--- /dev/null
+++ b/models-pap/src/test/java/org/onap/policy/models/pap/persistence/provider/PolicyAuditProviderTest.java
@@ -0,0 +1,241 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.models.pap.persistence.provider;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertThrows;
+import static org.junit.Assert.assertTrue;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Properties;
+import java.util.concurrent.TimeUnit;
+import org.awaitility.Awaitility;
+import org.eclipse.persistence.config.PersistenceUnitProperties;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.onap.policy.models.dao.DaoParameters;
+import org.onap.policy.models.dao.PfDao;
+import org.onap.policy.models.dao.PfDaoFactory;
+import org.onap.policy.models.dao.impl.DefaultPfDao;
+import org.onap.policy.models.pap.concepts.PolicyAudit;
+import org.onap.policy.models.pap.concepts.PolicyAudit.AuditAction;
+import org.onap.policy.models.pap.persistence.provider.PolicyAuditProvider.AuditFilter;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+/**
+ * Class for unit testing {@link PolicyAuditProvider}.
+ *
+ * @author Adheli Tavares (adheli.tavares@est.tech)
+ *
+ */
+public class PolicyAuditProviderTest {
+
+ private static final String FIELD_IS_NULL = "%s is marked .*ull but is null";
+ private static final String GROUP_A = "groupA";
+ private static final String GROUP_B = "groupB";
+ private static final ToscaConceptIdentifier MY_POLICY = new ToscaConceptIdentifier("MyPolicy", "1.2.3");
+ private static final ToscaConceptIdentifier MY_POLICY2 = new ToscaConceptIdentifier("MyPolicyB", "2.3.4");
+ private static final Integer NUMBER_RECORDS = 10;
+
+ private PfDao pfDao;
+
+ /**
+ * Set up the DAO towards the database.
+ *
+ * @throws Exception on database errors
+ */
+ @Before
+ public void setupDao() throws Exception {
+ final DaoParameters daoParameters = new DaoParameters();
+ daoParameters.setPluginClass(DefaultPfDao.class.getName());
+
+ daoParameters.setPersistenceUnit("ToscaConceptTest");
+
+ Properties jdbcProperties = new Properties();
+ jdbcProperties.setProperty(PersistenceUnitProperties.JDBC_USER, "policy");
+ jdbcProperties.setProperty(PersistenceUnitProperties.JDBC_PASSWORD, "P01icY");
+
+ if (System.getProperty("USE-MARIADB") != null) {
+ jdbcProperties.setProperty(PersistenceUnitProperties.JDBC_DRIVER, "org.mariadb.jdbc.Driver");
+ jdbcProperties.setProperty(PersistenceUnitProperties.JDBC_URL, "jdbc:mariadb://localhost:3306/policy");
+ } else {
+ jdbcProperties.setProperty(PersistenceUnitProperties.JDBC_DRIVER, "org.h2.Driver");
+ jdbcProperties.setProperty(PersistenceUnitProperties.JDBC_URL, "jdbc:h2:mem:PolicyAuditProviderTest");
+ }
+
+ daoParameters.setJdbcProperties(jdbcProperties);
+
+ pfDao = new PfDaoFactory().createPfDao(daoParameters);
+ pfDao.init(daoParameters);
+ }
+
+ @After
+ public void teardown() {
+ pfDao.close();
+ }
+
+ @Test
+ public void testCreatePolicyAudit() {
+ PolicyAuditProvider provider = new PolicyAuditProvider();
+
+ Instant date = Instant.now();
+ provider.createAuditRecords(pfDao, generatePolicyAudits(date, GROUP_A, MY_POLICY));
+
+ List<PolicyAudit> records = provider.getAuditRecords(pfDao, NUMBER_RECORDS);
+ assertThat(records).hasSize(2);
+
+ // as the start date is 10 min ahead of first record, shouldn't return any records
+ List<PolicyAudit> emptyList = provider.getAuditRecords(pfDao,
+ AuditFilter.builder().fromDate(Instant.now().plusSeconds(600)).build(), 600);
+ assertThat(emptyList).isEmpty();
+ }
+
+ @Test
+ public void testCreatePolicyAuditInvalid() {
+ PolicyAuditProvider provider = new PolicyAuditProvider();
+
+ List<PolicyAudit> audits = List.of(PolicyAudit.builder().pdpType("pdpType").action(AuditAction.DEPLOYMENT)
+ .timestamp(Instant.now()).build());
+
+ assertThrows(PfModelRuntimeException.class, () -> provider.createAuditRecords(pfDao, audits));
+
+ List<PolicyAudit> records = provider.getAuditRecords(pfDao, NUMBER_RECORDS);
+ assertThat(records).isEmpty();
+ }
+
+ @Test
+ public void testFilters() {
+ PolicyAuditProvider provider = new PolicyAuditProvider();
+
+ Instant date = Instant.now().truncatedTo(ChronoUnit.SECONDS);
+ System.out.println(date);
+ provider.createAuditRecords(pfDao, generatePolicyAudits(date, GROUP_A, MY_POLICY));
+ provider.createAuditRecords(pfDao, generatePolicyAudits(date, GROUP_B, MY_POLICY));
+ provider.createAuditRecords(pfDao, generatePolicyAudits(date, GROUP_B, MY_POLICY2));
+ Awaitility.await().pollDelay(3, TimeUnit.SECONDS).until(() -> {
+ return true;
+ });
+
+ List<PolicyAudit> records = provider.getAuditRecords(pfDao,
+ AuditFilter.builder().fromDate(date).toDate(Instant.now()).build(), NUMBER_RECORDS);
+ assertThat(records).hasSize(6);
+
+ List<PolicyAudit> recordsWithGroupB =
+ provider.getAuditRecords(pfDao, AuditFilter.builder().pdpGroup(GROUP_B).build(), NUMBER_RECORDS);
+ assertThat(recordsWithGroupB).hasSize(4);
+
+ List<PolicyAudit> recordsWithActionDeploy = provider.getAuditRecords(pfDao,
+ AuditFilter.builder().action(AuditAction.DEPLOYMENT).build(), NUMBER_RECORDS);
+ assertThat(recordsWithActionDeploy).hasSize(3);
+
+ List<PolicyAudit> recordsWithMyPolicy = provider.getAuditRecords(pfDao,
+ AuditFilter.builder().name(MY_POLICY.getName()).version(MY_POLICY.getVersion()).build(),
+ NUMBER_RECORDS);
+ assertThat(recordsWithMyPolicy).hasSize(4);
+ }
+
+ @Test
+ public void testLoadRecordsForLimit() {
+ PolicyAuditProvider provider = new PolicyAuditProvider();
+
+ List<PolicyAudit> loadAudits = new ArrayList<>();
+
+ // going to create 102 records.
+ for (int i = 0; i <= 50; i++) {
+ loadAudits.addAll(generatePolicyAudits(Instant.now().plusSeconds(i), GROUP_A, MY_POLICY));
+ }
+
+ provider.createAuditRecords(pfDao, loadAudits);
+
+ List<PolicyAudit> records = provider.getAuditRecords(pfDao, NUMBER_RECORDS);
+ assertThat(records).hasSize(10);
+
+ // check that is being ordered
+ assertTrue(records.get(0).getTimestamp().isAfter(records.get(9).getTimestamp()));
+ assertEquals(loadAudits.get(loadAudits.size() - 1).getTimestamp(), records.get(0).getTimestamp());
+
+ // try to get 102 records should return 100
+ records = provider.getAuditRecords(pfDao, 102);
+ assertThat(records).hasSize(100);
+ }
+
+ @Test
+ public void policyProviderExceptions() {
+ PolicyAuditProvider provider = new PolicyAuditProvider();
+
+ assertThatThrownBy(() -> {
+ provider.createAuditRecords(null, null);
+ }).hasMessageMatching(String.format(FIELD_IS_NULL, "dao"));
+
+ assertThatThrownBy(() -> {
+ provider.createAuditRecords(pfDao, null);
+ }).hasMessageMatching(String.format(FIELD_IS_NULL, "audits"));
+
+ assertThatThrownBy(() -> {
+ provider.getAuditRecords(null, NUMBER_RECORDS);
+ }).hasMessageMatching(String.format(FIELD_IS_NULL, "dao"));
+
+ assertThatThrownBy(() -> {
+ provider.getAuditRecords(pfDao, null);
+ }).hasMessageMatching(String.format(FIELD_IS_NULL, "numRecords"));
+
+ assertThatThrownBy(() -> {
+ provider.getAuditRecords(null, AuditFilter.builder().build(), NUMBER_RECORDS);
+ }).hasMessageMatching(String.format(FIELD_IS_NULL, "dao"));
+
+ assertThatThrownBy(() -> {
+ provider.getAuditRecords(pfDao, AuditFilter.builder().build(), null);
+ }).hasMessageMatching(String.format(FIELD_IS_NULL, "numRecords"));
+
+ assertThatThrownBy(() -> {
+ provider.getAuditRecords(pfDao, null, NUMBER_RECORDS);
+ }).hasMessageMatching(String.format(FIELD_IS_NULL, "auditFilter"));
+ }
+
+ private List<PolicyAudit> generatePolicyAudits(Instant date, String group, ToscaConceptIdentifier policy) {
+ // @formatter:off
+ PolicyAudit deploy = PolicyAudit.builder()
+ .pdpGroup(group)
+ .pdpType("pdpType")
+ .policy(policy)
+ .action(AuditAction.DEPLOYMENT)
+ .timestamp(date.truncatedTo(ChronoUnit.SECONDS))
+ .build();
+
+ PolicyAudit undeploy = PolicyAudit.builder()
+ .pdpGroup(group)
+ .pdpType("pdpType")
+ .policy(policy)
+ .action(AuditAction.UNDEPLOYMENT)
+ .timestamp(date.plusSeconds(1).truncatedTo(ChronoUnit.SECONDS))
+ .build();
+ // @formatter:on
+
+ return List.of(deploy, undeploy);
+ }
+}
diff --git a/models-pap/src/test/resources/META-INF/persistence.xml b/models-pap/src/test/resources/META-INF/persistence.xml
new file mode 100644
index 000000000..58e2deca3
--- /dev/null
+++ b/models-pap/src/test/resources/META-INF/persistence.xml
@@ -0,0 +1,46 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+ ============LICENSE_START=======================================================
+ Copyright (C) 2021 Nordix Foundation.
+ ================================================================================
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ SPDX-License-Identifier: Apache-2.0
+ ============LICENSE_END=========================================================
+-->
+
+<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
+ <persistence-unit name="ToscaConceptTest" transaction-type="RESOURCE_LOCAL">
+ <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
+
+ <class>org.onap.policy.models.pap.persistence.concepts.JpaPolicyAudit</class>
+
+ <properties>
+ <property name="eclipselink.target-database" value="MySQL" />
+ <property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
+ <property name="eclipselink.ddl-generation.output-mode" value="database" />
+ <property name="eclipselink.logging.level" value="INFO" />
+
+ <property name="eclipselink.logging.level" value="ALL" />
+ <property name="eclipselink.logging.level.jpa" value="ALL" />
+ <property name="eclipselink.logging.level.ddl" value="ALL" />
+ <property name="eclipselink.logging.level.connection" value="ALL" />
+ <property name="eclipselink.logging.level.sql" value="ALL" />
+ <property name="eclipselink.logging.level.transaction" value="ALL" />
+ <property name="eclipselink.logging.level.sequencing" value="ALL" />
+ <property name="eclipselink.logging.level.server" value="ALL" />
+ <property name="eclipselink.logging.level.query" value="ALL" />
+ <property name="eclipselink.logging.level.properties" value="ALL" />
+ </properties>
+ </persistence-unit>
+</persistence>