diff options
18 files changed, 589 insertions, 118 deletions
diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/Participant.java b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/Participant.java index 6a523fa75..c6da3c3d1 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/Participant.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/Participant.java @@ -20,6 +20,7 @@ package org.onap.policy.clamp.models.acm.concepts; +import java.util.UUID; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.NoArgsConstructor; @@ -35,6 +36,9 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaEntity; @Data @EqualsAndHashCode(callSuper = true) public class Participant extends ToscaEntity implements Comparable<Participant> { + + @NonNull + private UUID participantId; @NonNull private ToscaConceptIdentifier definition = new ToscaConceptIdentifier(PfConceptKey.getNullKey()); @@ -69,5 +73,6 @@ public class Participant extends ToscaEntity implements Comparable<Participant> this.definition = new ToscaConceptIdentifier(otherParticipant.definition); this.participantState = otherParticipant.participantState; this.participantType = otherParticipant.participantType; + this.participantId = otherParticipant.participantId; } } diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaParticipant.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaParticipant.java index aec2d32d3..398daa245 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaParticipant.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaParticipant.java @@ -22,6 +22,7 @@ package org.onap.policy.clamp.models.acm.persistence.concepts; import java.io.Serializable; import java.util.List; +import java.util.UUID; import javax.persistence.AttributeOverride; import javax.persistence.Column; import javax.persistence.EmbeddedId; @@ -56,6 +57,10 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; public class JpaParticipant extends PfConcept implements PfAuthorative<Participant>, Serializable { private static final long serialVersionUID = -4697758484642403483L; + @Column + @NotNull + private String participantId; + @EmbeddedId @VerifyKey @NotNull @@ -94,21 +99,25 @@ public class JpaParticipant extends PfConcept implements PfAuthorative<Participa * @param key the key */ public JpaParticipant(@NonNull final PfConceptKey key) { - this(key, new PfConceptKey(), ParticipantState.ON_LINE); + this(UUID.randomUUID().toString(), key, new PfConceptKey(), ParticipantState.ON_LINE); } /** * The Key Constructor creates a {@link JpaParticipant} object with all mandatory fields. * + * @param participantId the participant id * @param key the key * @param definition the TOSCA definition of the participant * @param participantState the state of the participant */ - public JpaParticipant(@NonNull final PfConceptKey key, @NonNull final PfConceptKey definition, - @NonNull final ParticipantState participantState) { + public JpaParticipant(@NotNull String participantId, + @NonNull final PfConceptKey key, + @NonNull final PfConceptKey definition, + @NonNull final ParticipantState participantState) { this.key = key; this.definition = definition; this.participantState = participantState; + this.participantId = participantId; } /** @@ -123,6 +132,7 @@ public class JpaParticipant extends PfConcept implements PfAuthorative<Participa this.participantState = copyConcept.participantState; this.description = copyConcept.description; this.participantType = copyConcept.participantType; + this.participantId = copyConcept.participantId; } /** @@ -144,6 +154,7 @@ public class JpaParticipant extends PfConcept implements PfAuthorative<Participa participant.setParticipantState(participantState); participant.setDescription(description); participant.setParticipantType(new ToscaConceptIdentifier(participantType)); + participant.setParticipantId(UUID.fromString(participantId)); return participant; } @@ -158,6 +169,7 @@ public class JpaParticipant extends PfConcept implements PfAuthorative<Participa this.setParticipantState(participant.getParticipantState()); this.setDescription(participant.getDescription()); this.participantType = participant.getParticipantType().asConceptKey(); + this.participantId = participant.getParticipantId().toString(); } @Override diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java index 3f7e297a4..91766807f 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProvider.java @@ -22,12 +22,14 @@ package org.onap.policy.clamp.models.acm.persistence.provider; import java.util.List; import java.util.Optional; +import java.util.UUID; import javax.ws.rs.core.Response.Status; import lombok.NonNull; import lombok.RequiredArgsConstructor; import org.onap.policy.clamp.models.acm.concepts.Participant; import org.onap.policy.clamp.models.acm.persistence.concepts.JpaParticipant; import org.onap.policy.clamp.models.acm.persistence.repository.ParticipantRepository; +import org.onap.policy.models.base.PfModelException; import org.onap.policy.models.base.PfModelRuntimeException; import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; import org.springframework.stereotype.Service; @@ -69,6 +71,24 @@ public class ParticipantProvider { /** * Get participant. * + * @param participantId the id of the participant to get + * @return the participant found + * @throws PfModelException on errors getting participant + */ + @Transactional(readOnly = true) + public Participant getParticipantById(String participantId) { + var participant = participantRepository.findByParticipantId(participantId); + if (participant.isEmpty()) { + throw new PfModelRuntimeException(Status.NOT_FOUND, + "Participant Not Found with ID: " + participantId); + } else { + return participant.get().toAuthorative(); + } + } + + /** + * Get participant. + * * @param participantId the Id of the participant to get * @return the participant found */ @@ -84,8 +104,23 @@ public class ParticipantProvider { * @return the participant created */ public Participant saveParticipant(@NonNull final Participant participant) { + participant.setParticipantId(UUID.randomUUID()); + var result = participantRepository + .save(ProviderUtils.getJpaAndValidate(participant, JpaParticipant::new, "participant")); + + // Return the saved participant + return result.toAuthorative(); + } + + /** + * Updates an existing participant. + * + * @param participant participant to update + * @return the participant updated + */ + public Participant updateParticipant(@NonNull final Participant participant) { var result = participantRepository - .save(ProviderUtils.getJpaAndValidate(participant, JpaParticipant::new, "participant")); + .save(ProviderUtils.getJpaAndValidate(participant, JpaParticipant::new, "participant")); // Return the saved participant return result.toAuthorative(); @@ -102,7 +137,7 @@ public class ParticipantProvider { if (jpaDeleteParticipantOpt.isEmpty()) { String errorMessage = - "delete of participant \"" + participantId + "\" failed, participant does not exist"; + "delete of participant \"" + participantId + "\" failed, participant does not exist"; throw new PfModelRuntimeException(Status.BAD_REQUEST, errorMessage); } participantRepository.delete(jpaDeleteParticipantOpt.get()); diff --git a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/ParticipantRepository.java b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/ParticipantRepository.java index 2279a75cc..67ea18870 100644 --- a/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/ParticipantRepository.java +++ b/models/src/main/java/org/onap/policy/clamp/models/acm/persistence/repository/ParticipantRepository.java @@ -1,6 +1,6 @@ /*- * ============LICENSE_START======================================================= - * Copyright (C) 2021 Nordix Foundation. + * Copyright (C) 2021-2023 Nordix Foundation. * ================================================================================ * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -20,6 +20,7 @@ package org.onap.policy.clamp.models.acm.persistence.repository; +import java.util.Optional; import org.onap.policy.clamp.models.acm.persistence.concepts.JpaParticipant; import org.onap.policy.models.base.PfConceptKey; import org.springframework.data.jpa.repository.JpaRepository; @@ -28,4 +29,5 @@ import org.springframework.stereotype.Repository; @Repository public interface ParticipantRepository extends JpaRepository<JpaParticipant, PfConceptKey>, FilterRepository { + Optional<JpaParticipant> findByParticipantId(String compositionId); } diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaParticipantTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaParticipantTest.java index 9d1d7ff99..0fbdaa2bc 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaParticipantTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/concepts/JpaParticipantTest.java @@ -27,6 +27,7 @@ import static org.junit.jupiter.api.Assertions.assertNotEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; +import java.util.UUID; import org.junit.jupiter.api.Test; import org.onap.policy.clamp.models.acm.concepts.Participant; import org.onap.policy.clamp.models.acm.concepts.ParticipantState; @@ -47,52 +48,54 @@ class JpaParticipantTest { assertThatThrownBy(() -> new JpaParticipant((PfConceptKey) null)).hasMessageMatching(NULL_KEY_ERROR); - assertThatThrownBy(() -> new JpaParticipant(null, null, null)).hasMessageMatching(NULL_KEY_ERROR); + assertThatThrownBy(() -> new JpaParticipant(null, null, null, null)).hasMessageMatching(NULL_KEY_ERROR); - assertThatThrownBy(() -> new JpaParticipant(null, null, null)) + assertThatThrownBy(() -> new JpaParticipant(null, null, null, null)) .hasMessageMatching(NULL_KEY_ERROR); - assertThatThrownBy(() -> new JpaParticipant(null, null, ParticipantState.ON_LINE)) + assertThatThrownBy(() -> new JpaParticipant(null, null, null, ParticipantState.ON_LINE)) .hasMessageMatching(NULL_KEY_ERROR); assertThatThrownBy( - () -> new JpaParticipant(null, null, ParticipantState.ON_LINE)) + () -> new JpaParticipant(null, null, null, ParticipantState.ON_LINE)) .hasMessageMatching(NULL_KEY_ERROR); - assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null)) + assertThatThrownBy(() -> new JpaParticipant(null, null, new PfConceptKey(), null)) .hasMessageMatching(NULL_KEY_ERROR); - assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null)) + assertThatThrownBy(() -> new JpaParticipant(null, null, new PfConceptKey(), null)) .hasMessageMatching(NULL_KEY_ERROR); - assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), ParticipantState.ON_LINE)) + assertThatThrownBy(() -> new JpaParticipant(null, null, new PfConceptKey(), ParticipantState.ON_LINE)) .hasMessageMatching(NULL_KEY_ERROR); - assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), ParticipantState.ON_LINE)) + assertThatThrownBy(() -> new JpaParticipant(null, null, new PfConceptKey(), ParticipantState.ON_LINE)) .hasMessageMatching(NULL_KEY_ERROR); - assertThatThrownBy(() -> new JpaParticipant(new PfConceptKey(), null, null)) + assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null, null)) .hasMessageMatching("definition is marked .*ull but is null"); - assertThatThrownBy(() -> new JpaParticipant(new PfConceptKey(), null, null)) + assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null, null)) .hasMessageMatching("definition is marked .*ull but is null"); - assertThatThrownBy(() -> new JpaParticipant(new PfConceptKey(), null, ParticipantState.ON_LINE)) + assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null, ParticipantState.ON_LINE)) .hasMessageMatching("definition is marked .*ull but is null"); - assertThatThrownBy(() -> new JpaParticipant(new PfConceptKey(), null, ParticipantState.ON_LINE - )).hasMessageMatching("definition is marked .*ull but is null"); + assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), null, ParticipantState.ON_LINE + )).hasMessageMatching("definition is marked .*ull but is null"); - assertThatThrownBy(() -> new JpaParticipant(new PfConceptKey(), new PfConceptKey(), null)) + assertThatThrownBy(() -> new JpaParticipant(null, new PfConceptKey(), new PfConceptKey(), null)) .hasMessageMatching("participantState is marked .*ull but is null"); assertThatThrownBy( - () -> new JpaParticipant(new PfConceptKey(), new PfConceptKey(), null)) + () -> new JpaParticipant(null, new PfConceptKey(), new PfConceptKey(), null)) .hasMessageMatching("participantState is marked .*ull but is null"); assertNotNull(new JpaParticipant()); assertNotNull(new JpaParticipant((new PfConceptKey()))); - assertNotNull(new JpaParticipant(new PfConceptKey(), new PfConceptKey(), ParticipantState.ON_LINE)); + assertNotNull(new JpaParticipant(null, new PfConceptKey(), new PfConceptKey(), ParticipantState.ON_LINE)); + assertNotNull(new JpaParticipant(UUID.randomUUID().toString(), new PfConceptKey(), + new PfConceptKey(), ParticipantState.ON_LINE)); } @Test @@ -100,6 +103,9 @@ class JpaParticipantTest { JpaParticipant testJpaParticipant = createJpaParticipantInstance(); Participant participant = createParticipantInstance(); + + participant.setParticipantId(testJpaParticipant.toAuthorative().getParticipantId()); + assertEquals(participant, testJpaParticipant.toAuthorative()); assertThatThrownBy(() -> testJpaParticipant.fromAuthorative(null)) @@ -110,6 +116,7 @@ class JpaParticipantTest { JpaParticipant testJpaParticipantFa = new JpaParticipant(); testJpaParticipantFa.setKey(null); testJpaParticipantFa.fromAuthorative(participant); + testJpaParticipantFa.setParticipantId(testJpaParticipant.getParticipantId()); assertEquals(testJpaParticipant, testJpaParticipantFa); testJpaParticipantFa.setKey(PfConceptKey.getNullKey()); testJpaParticipantFa.fromAuthorative(participant); @@ -119,9 +126,9 @@ class JpaParticipantTest { assertEquals(testJpaParticipant, testJpaParticipantFa); assertEquals("participant", testJpaParticipant.getKey().getName()); - assertEquals("participant", new JpaParticipant(createParticipantInstance()).getKey().getName()); + assertEquals("participant", new JpaParticipant(createJpaParticipantInstance()).getKey().getName()); assertEquals("participant", - ((PfConceptKey) new JpaParticipant(createParticipantInstance()).getKeys().get(0)).getName()); + ((PfConceptKey) new JpaParticipant(createJpaParticipantInstance()).getKeys().get(0)).getName()); testJpaParticipant.clean(); assertEquals("participant", testJpaParticipant.getKey().getName()); @@ -131,6 +138,7 @@ class JpaParticipantTest { assertEquals("A Message", testJpaParticipant.getDescription()); JpaParticipant testJpaParticipant2 = new JpaParticipant(testJpaParticipant); + testJpaParticipant2.setParticipantId(testJpaParticipant.getParticipantId()); assertEquals(testJpaParticipant, testJpaParticipant2); } @@ -149,6 +157,7 @@ class JpaParticipantTest { JpaParticipant testJpaParticipant = createJpaParticipantInstance(); JpaParticipant otherJpaParticipant = new JpaParticipant(testJpaParticipant); + otherJpaParticipant.setParticipantId(testJpaParticipant.getParticipantId()); assertEquals(0, testJpaParticipant.compareTo(otherJpaParticipant)); assertEquals(-1, testJpaParticipant.compareTo(null)); assertEquals(0, testJpaParticipant.compareTo(testJpaParticipant)); @@ -169,6 +178,10 @@ class JpaParticipantTest { testJpaParticipant.setParticipantState(ParticipantState.ON_LINE); assertEquals(0, testJpaParticipant.compareTo(otherJpaParticipant)); assertEquals(testJpaParticipant, new JpaParticipant(testJpaParticipant)); + + JpaParticipant newJpaParticipant = new JpaParticipant(testJpaParticipant); + newJpaParticipant.setParticipantId(testJpaParticipant.getParticipantId()); + assertEquals(testJpaParticipant, newJpaParticipant); } @Test @@ -197,6 +210,7 @@ class JpaParticipantTest { assertNotEquals(p1, p0); JpaParticipant p2 = new JpaParticipant(); + p2.setParticipantId(p0.getParticipantId()); assertEquals(p2, p0); } @@ -204,6 +218,7 @@ class JpaParticipantTest { Participant testParticipant = createParticipantInstance(); JpaParticipant testJpaParticipant = new JpaParticipant(); testJpaParticipant.setKey(null); + testParticipant.setParticipantId(UUID.fromString(testJpaParticipant.getParticipantId())); testJpaParticipant.fromAuthorative(testParticipant); testJpaParticipant.setKey(PfConceptKey.getNullKey()); testJpaParticipant.fromAuthorative(testParticipant); diff --git a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java index e11541988..6e6637c7e 100644 --- a/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java +++ b/models/src/test/java/org/onap/policy/clamp/models/acm/persistence/provider/ParticipantProviderTest.java @@ -64,7 +64,7 @@ class ParticipantProviderTest { var participantRepository = mock(ParticipantRepository.class); for (var participant : jpaParticipantList) { when(participantRepository.getById(new PfConceptKey(participant.getName(), participant.getVersion()))) - .thenReturn(participant); + .thenReturn(participant); } var participantProvider = new ParticipantProvider(participantRepository); @@ -73,10 +73,30 @@ class ParticipantProviderTest { when(participantRepository.save(any())).thenReturn(jpaParticipantList.get(0)); Participant savedParticipant = participantProvider.saveParticipant(inputParticipants.get(0)); + savedParticipant.setParticipantId(inputParticipants.get(0).getParticipantId()); assertEquals(savedParticipant, inputParticipants.get(0)); } @Test + void testParticipantUpdate() throws Exception { + var participantRepository = mock(ParticipantRepository.class); + for (var participant : jpaParticipantList) { + when(participantRepository.getById(new PfConceptKey(participant.getName(), participant.getVersion()))) + .thenReturn(participant); + } + var participantProvider = new ParticipantProvider(participantRepository); + + assertThatThrownBy(() -> participantProvider.updateParticipant(null)) + .hasMessageMatching(LIST_IS_NULL); + + when(participantRepository.save(any())).thenReturn(jpaParticipantList.get(0)); + + Participant updatedParticipant = participantProvider.updateParticipant(inputParticipants.get(0)); + updatedParticipant.setParticipantId(inputParticipants.get(0).getParticipantId()); + assertEquals(updatedParticipant, inputParticipants.get(0)); + } + + @Test void testGetAutomationCompositions() throws Exception { var participantRepository = mock(ParticipantRepository.class); var participantProvider = new ParticipantProvider(participantRepository); @@ -88,7 +108,7 @@ class ParticipantProviderTest { String name = inputParticipants.get(0).getName(); String version = inputParticipants.get(0).getVersion(); when(participantRepository.getFiltered(any(), eq(name), eq(version))) - .thenReturn(List.of(jpaParticipantList.get(0))); + .thenReturn(List.of(jpaParticipantList.get(0))); assertEquals(1, participantProvider.getParticipants(name, version).size()); assertThat(participantProvider.getParticipants("invalid_name", "1.0.1")).isEmpty(); @@ -97,6 +117,14 @@ class ParticipantProviderTest { when(participantRepository.findAll()).thenReturn(jpaParticipantList); assertThat(participantProvider.getParticipants()).hasSize(inputParticipants.size()); + + when(participantRepository.findByParticipantId(any())).thenReturn( + Optional.ofNullable(jpaParticipantList.get(0))); + + var participant = participantProvider.getParticipantById(inputParticipants.get(0) + .getParticipantId().toString()); + + assertThat(participant).isEqualTo(inputParticipants.get(0)); } @Test @@ -105,12 +133,12 @@ class ParticipantProviderTest { var participantProvider = new ParticipantProvider(participantRepository); assertThatThrownBy(() -> participantProvider.deleteParticipant(INVALID_ID)) - .hasMessageMatching(".*.failed, participant does not exist"); + .hasMessageMatching(".*.failed, participant does not exist"); when(participantRepository.findById(any())).thenReturn(Optional.of(jpaParticipantList.get(0))); Participant deletedParticipant = - participantProvider.deleteParticipant(inputParticipants.get(0).getDefinition()); + participantProvider.deleteParticipant(inputParticipants.get(0).getDefinition()); assertEquals(inputParticipants.get(0), deletedParticipant); } } diff --git a/models/src/test/resources/providers/TestParticipant.json b/models/src/test/resources/providers/TestParticipant.json index 5d8a7ea09..99284cb6a 100644 --- a/models/src/test/resources/providers/TestParticipant.json +++ b/models/src/test/resources/providers/TestParticipant.json @@ -7,6 +7,7 @@ }, "participantState": "ON_LINE", "description": "A dummy PMSH participant1", + "participantId": "82fd8ef9-1d1e-4343-9b28-7f9564ee3de6", "participantType":{ "name": "org.onap.domain.pmsh.PolicyAutomationCompositionDefinition", "version": "1.0.0" diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/ParticipantController.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/ParticipantController.java new file mode 100644 index 000000000..abcef7a94 --- /dev/null +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/ParticipantController.java @@ -0,0 +1,67 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.main.rest; + +import java.util.List; +import java.util.UUID; +import lombok.RequiredArgsConstructor; +import org.onap.policy.clamp.acm.runtime.main.rest.gen.ParticipantMonitoringApi; +import org.onap.policy.clamp.acm.runtime.main.web.AbstractRestController; +import org.onap.policy.clamp.acm.runtime.participants.AcmParticipantProvider; +import org.onap.policy.clamp.models.acm.concepts.ParticipantInformation; +import org.springframework.context.annotation.Profile; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequiredArgsConstructor +@Profile("default") +public class ParticipantController extends AbstractRestController implements ParticipantMonitoringApi { + + private final AcmParticipantProvider acmParticipantProvider; + + @Override + public ResponseEntity<ParticipantInformation> getParticipant(UUID participantId, UUID requestId) { + ParticipantInformation participantInformation = acmParticipantProvider + .getParticipantById(participantId.toString()); + return ResponseEntity.ok().body(participantInformation); + } + + @Override + public ResponseEntity<Void> orderAllParticipantsReport(UUID requestId) { + acmParticipantProvider.sendAllParticipantStatusRequest(); + return new ResponseEntity<>(HttpStatus.ACCEPTED); + } + + @Override + public ResponseEntity<Void> orderParticipantReport(UUID participantId, UUID requestId) { + acmParticipantProvider.sendParticipantStatusRequest(participantId.toString()); + return new ResponseEntity<>(HttpStatus.ACCEPTED); + } + + @Override + public ResponseEntity<List<ParticipantInformation>> queryParticipants(String name, String version, + UUID requestId) { + List<ParticipantInformation> participantInformationList = acmParticipantProvider.getAllParticipants(); + return ResponseEntity.ok().body(participantInformationList); + } +} diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/participants/AcmParticipantProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/participants/AcmParticipantProvider.java new file mode 100644 index 000000000..e1d0423d1 --- /dev/null +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/participants/AcmParticipantProvider.java @@ -0,0 +1,102 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.participants; + +import java.util.ArrayList; +import java.util.List; +import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantStatusReqPublisher; +import org.onap.policy.clamp.models.acm.concepts.Participant; +import org.onap.policy.clamp.models.acm.concepts.ParticipantInformation; +import org.onap.policy.clamp.models.acm.concepts.ParticipantState; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; + +@Service +@Transactional +public class AcmParticipantProvider { + + private static final Logger LOGGER = LoggerFactory.getLogger(AcmParticipantProvider.class); + private final ParticipantProvider participantProvider; + private final ParticipantStatusReqPublisher participantStatusReqPublisher; + + public AcmParticipantProvider(ParticipantProvider participantProvider, + ParticipantStatusReqPublisher participantStatusReqPublisher) { + this.participantProvider = participantProvider; + this.participantStatusReqPublisher = participantStatusReqPublisher; + } + + /** + * Get all participants. + * + * @return A list of available participants + */ + public List<ParticipantInformation> getAllParticipants() { + List<Participant> participants = this.participantProvider.getParticipants(); + + List<ParticipantInformation> participantInformationList = new ArrayList<>(); + participants.forEach(participant -> { + ParticipantInformation participantInformation = new ParticipantInformation(); + participantInformation.setParticipant(participant); + participantInformationList.add(participantInformation); + }); + return participantInformationList; + } + + /** + * Get a participant. + * + * @param participantId The UUID of the participant to get + * @return The participant + */ + public ParticipantInformation getParticipantById(String participantId) { + Participant participant = this.participantProvider.getParticipantById(participantId); + ParticipantInformation participantInformation = new ParticipantInformation(); + participantInformation.setParticipant(participant); + return participantInformation; + } + + /** + * Send a participant status request. + * + * @param participantId The UUID of the participant to send request to + */ + public void sendParticipantStatusRequest(String participantId) { + Participant participant = this.participantProvider.getParticipantById(participantId); + ToscaConceptIdentifier id = participant.getKey().asIdentifier(); + + LOGGER.debug("Requesting Participant Status Now ParticipantStatusReq"); + participantStatusReqPublisher.send(id); + participant.setParticipantState(ParticipantState.OFF_LINE); + participantProvider.updateParticipant(participant); + } + + /** + * Send status request to all participants. + * + */ + public void sendAllParticipantStatusRequest() { + this.participantStatusReqPublisher.send((ToscaConceptIdentifier) null); + } +} diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java index c27447405..761c3800c 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionHandler.java @@ -57,9 +57,9 @@ public class SupervisionHandler { private static final Logger LOGGER = LoggerFactory.getLogger(SupervisionHandler.class); private static final String AUTOMATION_COMPOSITION_CANNOT_TRANSITION_FROM_STATE = - "Automation composition can't transition from state "; + "Automation composition can't transition from state "; private static final String AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE = - "Automation composition is already in state "; + "Automation composition is already in state "; private static final String TO_STATE = " to state "; private static final String AND_TRANSITIONING_TO_STATE = " and transitioning to state "; @@ -78,7 +78,7 @@ public class SupervisionHandler { */ public void handleSendCommissionMessage(AutomationCompositionDefinition acmDefinition) { LOGGER.debug("Participant update message with serviveTemplate {} being sent to all participants", - acmDefinition.getCompositionId()); + acmDefinition.getCompositionId()); participantUpdatePublisher.sendComissioningBroadcast(acmDefinition); } @@ -98,8 +98,8 @@ public class SupervisionHandler { */ @MessageIntercept @Timed( - value = "listener.automation_composition_update_ack", - description = "AUTOMATION_COMPOSITION_UPDATE_ACK messages received") + value = "listener.automation_composition_update_ack", + description = "AUTOMATION_COMPOSITION_UPDATE_ACK messages received") public void handleAutomationCompositionUpdateAckMessage(AutomationCompositionAck automationCompositionAckMessage) { LOGGER.debug("AutomationComposition Update Ack message received {}", automationCompositionAckMessage); setAcElementStateInDb(automationCompositionAckMessage); @@ -123,10 +123,10 @@ public class SupervisionHandler { */ @MessageIntercept @Timed( - value = "listener.automation_composition_statechange_ack", - description = "AUTOMATION_COMPOSITION_STATECHANGE_ACK messages received") + value = "listener.automation_composition_statechange_ack", + description = "AUTOMATION_COMPOSITION_STATECHANGE_ACK messages received") public void handleAutomationCompositionStateChangeAckMessage( - AutomationCompositionAck automationCompositionAckMessage) { + AutomationCompositionAck automationCompositionAckMessage) { LOGGER.debug("AutomationComposition StateChange Ack message received {}", automationCompositionAckMessage); setAcElementStateInDb(automationCompositionAckMessage); } @@ -134,23 +134,23 @@ public class SupervisionHandler { private void setAcElementStateInDb(AutomationCompositionAck automationCompositionAckMessage) { if (automationCompositionAckMessage.getAutomationCompositionResultMap() != null) { var automationComposition = automationCompositionProvider - .findAutomationComposition(automationCompositionAckMessage.getAutomationCompositionId()); + .findAutomationComposition(automationCompositionAckMessage.getAutomationCompositionId()); if (automationComposition.isPresent()) { var updated = updateState(automationComposition.get(), - automationCompositionAckMessage.getAutomationCompositionResultMap().entrySet()); + automationCompositionAckMessage.getAutomationCompositionResultMap().entrySet()); updated |= setPrimed(automationComposition.get()); if (updated) { automationCompositionProvider.updateAutomationComposition(automationComposition.get()); } } else { LOGGER.warn("AutomationComposition not found in database {}", - automationCompositionAckMessage.getAutomationCompositionId()); + automationCompositionAckMessage.getAutomationCompositionId()); } } } private boolean updateState(AutomationComposition automationComposition, - Set<Map.Entry<UUID, AutomationCompositionElementAck>> automationCompositionResultSet) { + Set<Map.Entry<UUID, AutomationCompositionElementAck>> automationCompositionResultSet) { var updated = false; for (var acElementAck : automationCompositionResultSet) { var element = automationComposition.getElements().get(acElementAck.getKey()); @@ -167,9 +167,9 @@ public class SupervisionHandler { if (acElements != null) { Boolean primedFlag = true; var checkOpt = automationComposition.getElements().values().stream() - .filter(acElement -> (!acElement.getState().equals(AutomationCompositionState.PASSIVE) - || !acElement.getState().equals(AutomationCompositionState.RUNNING))) - .findAny(); + .filter(acElement -> (!acElement.getState().equals(AutomationCompositionState.PASSIVE) + || !acElement.getState().equals(AutomationCompositionState.RUNNING))) + .findAny(); if (checkOpt.isEmpty()) { primedFlag = false; } @@ -188,7 +188,7 @@ public class SupervisionHandler { * @throws AutomationCompositionException on supervision errors */ public void triggerAutomationCompositionSupervision(AutomationComposition automationComposition) - throws AutomationCompositionException { + throws AutomationCompositionException { switch (automationComposition.getOrderedState()) { case UNINITIALISED: superviseAutomationCompositionUninitialization(automationComposition); @@ -204,8 +204,8 @@ public class SupervisionHandler { default: exceptionOccured(Response.Status.NOT_ACCEPTABLE, - "A automation composition cannot be commanded to go into state " - + automationComposition.getOrderedState().name()); + "A automation composition cannot be commanded to go into state " + + automationComposition.getOrderedState().name()); } } @@ -218,39 +218,39 @@ public class SupervisionHandler { * @throws AutomationCompositionException on supervision errors */ private void superviseAutomationCompositionUninitialization(AutomationComposition automationComposition) - throws AutomationCompositionException { + throws AutomationCompositionException { switch (automationComposition.getState()) { case UNINITIALISED: exceptionOccured(Response.Status.NOT_ACCEPTABLE, - AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()); + AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()); break; case UNINITIALISED2PASSIVE: case PASSIVE: automationComposition.setState(AutomationCompositionState.PASSIVE2UNINITIALISED); automationCompositionStateChangePublisher.send(automationComposition, - getFirstStartPhase(automationComposition)); + getFirstStartPhase(automationComposition)); break; case PASSIVE2UNINITIALISED: exceptionOccured(Response.Status.NOT_ACCEPTABLE, - AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name() - + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState()); + AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name() + + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState()); break; default: exceptionOccured(Response.Status.NOT_ACCEPTABLE, AUTOMATION_COMPOSITION_CANNOT_TRANSITION_FROM_STATE - + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState()); + + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState()); break; } } private void superviseAutomationCompositionPassivation(AutomationComposition automationComposition) - throws AutomationCompositionException { + throws AutomationCompositionException { switch (automationComposition.getState()) { case PASSIVE: exceptionOccured(Response.Status.NOT_ACCEPTABLE, - AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()); + AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()); break; case UNINITIALISED: automationComposition.setState(AutomationCompositionState.UNINITIALISED2PASSIVE); @@ -260,46 +260,46 @@ public class SupervisionHandler { case UNINITIALISED2PASSIVE: case RUNNING2PASSIVE: exceptionOccured(Response.Status.NOT_ACCEPTABLE, - AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name() - + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState()); + AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name() + + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState()); break; case RUNNING: automationComposition.setState(AutomationCompositionState.RUNNING2PASSIVE); automationCompositionStateChangePublisher.send(automationComposition, - getFirstStartPhase(automationComposition)); + getFirstStartPhase(automationComposition)); break; default: exceptionOccured(Response.Status.NOT_ACCEPTABLE, AUTOMATION_COMPOSITION_CANNOT_TRANSITION_FROM_STATE - + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState()); + + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState()); break; } } private void superviseAutomationCompositionActivation(AutomationComposition automationComposition) - throws AutomationCompositionException { + throws AutomationCompositionException { switch (automationComposition.getState()) { case RUNNING: exceptionOccured(Response.Status.NOT_ACCEPTABLE, - AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()); + AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name()); break; case PASSIVE2RUNNING: exceptionOccured(Response.Status.NOT_ACCEPTABLE, - AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name() - + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState()); + AUTOMATION_COMPOSITION_IS_ALREADY_IN_STATE + automationComposition.getState().name() + + AND_TRANSITIONING_TO_STATE + automationComposition.getOrderedState()); break; case PASSIVE: automationComposition.setState(AutomationCompositionState.PASSIVE2RUNNING); automationCompositionStateChangePublisher.send(automationComposition, - getFirstStartPhase(automationComposition)); + getFirstStartPhase(automationComposition)); break; default: exceptionOccured(Response.Status.NOT_ACCEPTABLE, AUTOMATION_COMPOSITION_CANNOT_TRANSITION_FROM_STATE - + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState()); + + automationComposition.getState().name() + TO_STATE + automationComposition.getOrderedState()); break; } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java index da9187d22..2c9e84ba7 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java @@ -59,7 +59,7 @@ public class SupervisionParticipantHandler { saveParticipantStatus(participantRegisterMsg); participantRegisterAckPublisher.send(participantRegisterMsg.getMessageId(), - participantRegisterMsg.getParticipantId(), participantRegisterMsg.getParticipantType()); + participantRegisterMsg.getParticipantId(), participantRegisterMsg.getParticipantType()); } /** @@ -76,7 +76,7 @@ public class SupervisionParticipantHandler { if (participantOpt.isPresent()) { var participant = participantOpt.get(); participant.setParticipantState(ParticipantState.OFF_LINE); - participantProvider.saveParticipant(participant); + participantProvider.updateParticipant(participant); } participantDeregisterAckPublisher.send(participantDeregisterMsg.getMessageId()); @@ -110,7 +110,7 @@ public class SupervisionParticipantHandler { var participant = participantOpt.get(); participant.setParticipantState(ParticipantState.ON_LINE); - participantProvider.saveParticipant(participant); + participantProvider.updateParticipant(participant); } } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java index e595f3bee..f758c9893 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScanner.java @@ -71,10 +71,11 @@ public class SupervisionScanner { * @param acRuntimeParameterGroup the parameters for the automation composition runtime */ public SupervisionScanner(final AutomationCompositionProvider automationCompositionProvider, - AcDefinitionProvider acDefinitionProvider, - final AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher, - AutomationCompositionUpdatePublisher automationCompositionUpdatePublisher, - ParticipantProvider participantProvider, final AcRuntimeParameterGroup acRuntimeParameterGroup) { + AcDefinitionProvider acDefinitionProvider, + final AutomationCompositionStateChangePublisher automationCompositionStateChangePublisher, + AutomationCompositionUpdatePublisher automationCompositionUpdatePublisher, + ParticipantProvider participantProvider, + final AcRuntimeParameterGroup acRuntimeParameterGroup) { this.automationCompositionProvider = automationCompositionProvider; this.acDefinitionProvider = acDefinitionProvider; this.automationCompositionStateChangePublisher = automationCompositionStateChangePublisher; @@ -82,12 +83,12 @@ public class SupervisionScanner { this.participantProvider = participantProvider; automationCompositionCounter.setMaxRetryCount( - acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount()); + acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount()); automationCompositionCounter - .setMaxWaitMs(acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs()); + .setMaxWaitMs(acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs()); participantStatusCounter.setMaxRetryCount( - acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount()); + acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().getMaxRetryCount()); participantStatusCounter.setMaxWaitMs(acRuntimeParameterGroup.getParticipantParameters().getMaxStatusWaitMs()); } @@ -123,11 +124,11 @@ public class SupervisionScanner { return; } if (participantStatusCounter.getDuration(id) > participantStatusCounter.getMaxWaitMs() - && !participantStatusCounter.count(id)) { + && !participantStatusCounter.count(id)) { LOGGER.debug("report Participant fault"); participantStatusCounter.setFault(id); participant.setParticipantState(ParticipantState.OFF_LINE); - participantProvider.saveParticipant(participant); + participantProvider.updateParticipant(participant); } } @@ -139,7 +140,7 @@ public class SupervisionScanner { } private void scanAutomationComposition(final AutomationComposition automationComposition, - ToscaServiceTemplate toscaServiceTemplate, boolean counterCheck) { + ToscaServiceTemplate toscaServiceTemplate, boolean counterCheck) { LOGGER.debug("scanning automation composition {} . . .", automationComposition.getInstanceId()); if (automationComposition.getState().equals(automationComposition.getOrderedState().asState())) { @@ -157,7 +158,7 @@ public class SupervisionScanner { var defaultMax = 0; // max startPhase for (var element : automationComposition.getElements().values()) { var toscaNodeTemplate = toscaServiceTemplate.getToscaTopologyTemplate().getNodeTemplates() - .get(element.getDefinition().getName()); + .get(element.getDefinition().getName()); int startPhase = ParticipantUtils.findStartPhase(toscaNodeTemplate.getProperties()); defaultMin = Math.min(defaultMin, startPhase); defaultMax = Math.max(defaultMax, startPhase); @@ -170,7 +171,7 @@ public class SupervisionScanner { if (completed) { LOGGER.debug("automation composition scan: transition from state {} to {} completed", - automationComposition.getState(), automationComposition.getOrderedState()); + automationComposition.getState(), automationComposition.getOrderedState()); automationComposition.setState(automationComposition.getOrderedState().asState()); automationCompositionProvider.updateAutomationComposition(automationComposition); @@ -179,19 +180,19 @@ public class SupervisionScanner { clearFaultAndCounter(automationComposition); } else { LOGGER.debug("automation composition scan: transition from state {} to {} not completed", - automationComposition.getState(), automationComposition.getOrderedState()); + automationComposition.getState(), automationComposition.getOrderedState()); var nextSpNotCompleted = - AutomationCompositionState.UNINITIALISED2PASSIVE.equals(automationComposition.getState()) - || AutomationCompositionState.PASSIVE2RUNNING.equals(automationComposition.getState()) - ? minSpNotCompleted - : maxSpNotCompleted; + AutomationCompositionState.UNINITIALISED2PASSIVE.equals(automationComposition.getState()) + || AutomationCompositionState.PASSIVE2RUNNING.equals(automationComposition.getState()) + ? minSpNotCompleted + : maxSpNotCompleted; var firstStartPhase = - AutomationCompositionState.UNINITIALISED2PASSIVE.equals(automationComposition.getState()) - || AutomationCompositionState.PASSIVE2RUNNING.equals(automationComposition.getState()) - ? defaultMin - : defaultMax; + AutomationCompositionState.UNINITIALISED2PASSIVE.equals(automationComposition.getState()) + || AutomationCompositionState.PASSIVE2RUNNING.equals(automationComposition.getState()) + ? defaultMin + : defaultMax; if (nextSpNotCompleted != phaseMap.getOrDefault(automationComposition.getInstanceId(), firstStartPhase)) { phaseMap.put(automationComposition.getInstanceId(), nextSpNotCompleted); diff --git a/runtime-acm/src/main/resources/openapi/openapi.yaml b/runtime-acm/src/main/resources/openapi/openapi.yaml index 655ce7eeb..f2692a900 100644 --- a/runtime-acm/src/main/resources/openapi/openapi.yaml +++ b/runtime-acm/src/main/resources/openapi/openapi.yaml @@ -1,5 +1,5 @@ # ============LICENSE_START======================================================= -# Copyright (C) 2022 Nordix Foundation +# Copyright (C) 2022-2023 Nordix Foundation # ================================================================================ # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -65,7 +65,6 @@ paths: - name: X-onap-RequestId in: header description: RequestID for http transaction - required: true schema: type: string format: uuid @@ -138,7 +137,7 @@ paths: description: Requests all participants to immediately generate a heartbeat report with their information and status and the information and status of all their AC Element Types and Instances. The results are published on subsequent GET REST requests on the "participants" endpoint. - operationId: orderAllParticiantsReport + operationId: orderAllParticipantsReport parameters: - name: X-onap-RequestId in: header @@ -230,7 +229,6 @@ paths: - name: X-onap-RequestId in: header description: RequestID for http transaction - required: true schema: type: string format: uuid @@ -331,7 +329,6 @@ paths: format: uuid - name: X-onap-RequestId in: header - required: true description: RequestID for http transaction schema: type: string diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java new file mode 100644 index 000000000..e6f7118da --- /dev/null +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java @@ -0,0 +1,176 @@ +/*- + * ============LICENSE_START======================================================= + * Copyright (C) 2023 Nordix Foundation. + * ================================================================================ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + * ============LICENSE_END========================================================= + */ + +package org.onap.policy.clamp.acm.runtime.participant; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.GenericType; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.onap.policy.clamp.acm.runtime.main.rest.ParticipantController; +import org.onap.policy.clamp.acm.runtime.util.rest.CommonRestController; +import org.onap.policy.clamp.models.acm.concepts.Participant; +import org.onap.policy.clamp.models.acm.concepts.ParticipantInformation; +import org.onap.policy.clamp.models.acm.persistence.concepts.JpaParticipant; +import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.clamp.models.acm.persistence.provider.ProviderUtils; +import org.onap.policy.common.utils.coder.Coder; +import org.onap.policy.common.utils.coder.CoderException; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.base.PfModelException; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.web.server.LocalServerPort; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +/** + * Class to perform unit test of {@link ParticipantController}. + * + */ + +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) +@ActiveProfiles({ "test", "default" }) +public class ParticipantControllerTest extends CommonRestController { + private static final String PARTICIPANTS_ENDPOINT = "participants"; + + @LocalServerPort + private int randomServerPort; + + private static final Coder CODER = new StandardCoder(); + private static final String PARTICIPANT_JSON = "src/test/resources/providers/TestParticipant.json"; + private static final String PARTICIPANT_JSON2 = "src/test/resources/providers/TestParticipant2.json"; + private static final String LIST_IS_NULL = ".*. is marked .*ull but is null"; + + private static final List<Participant> inputParticipants = new ArrayList<>(); + private static List<JpaParticipant> jpaParticipantList; + private static final String originalJson = ResourceUtils.getResourceAsString(PARTICIPANT_JSON); + private static final String originalJson2 = ResourceUtils.getResourceAsString(PARTICIPANT_JSON2); + + @Autowired + private ParticipantProvider participantProvider; + + /** + * Adds participants to the db from json file. + */ + @BeforeAll + public static void setUpBeforeClass() throws CoderException { + inputParticipants.add(CODER.decode(originalJson, Participant.class)); + inputParticipants.add(CODER.decode(originalJson2, Participant.class)); + jpaParticipantList = ProviderUtils.getJpaAndValidateList( + inputParticipants, JpaParticipant::new, "participant"); + } + + @BeforeEach + public void setUpPort() { + super.setHttpPrefix(randomServerPort); + } + + @Test + void testSwagger() { + super.testSwagger(PARTICIPANTS_ENDPOINT); + } + + @Test + void testUnauthorizedQuery() { + assertUnauthorizedGet(PARTICIPANTS_ENDPOINT); + } + + @Test + void testQueryParticipant() { + participantProvider.saveParticipant(inputParticipants.get(0)); + UUID participantId = participantProvider.getParticipants().get(0).getParticipantId(); + var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + "/" + participantId); + var response = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + var entityList = response.readEntity(ParticipantInformation.class); + assertNotNull(entityList); + } + + @Test + void testBadQueryParticipant() { + participantProvider.saveParticipant(inputParticipants.get(0)); + UUID participantId = participantProvider.getParticipants().get(0).getParticipantId(); + var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + "/" + UUID.randomUUID()); + var response = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); + } + + @Test + void getAllParticipants() { + inputParticipants.forEach(p -> { + participantProvider.saveParticipant(p); + }); + var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT); + var response = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), response.getStatus()); + List<ParticipantInformation> entityList = response.readEntity(new GenericType<>() {}); + assertThat(entityList.size() == inputParticipants.size()); + } + + @Test + void testOrderParticipantReport() throws PfModelException { + participantProvider.saveParticipant(inputParticipants.get(0)); + UUID participantId = participantProvider.getParticipants().get(0).getParticipantId(); + var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + + "/" + + participantId); + var response = invocationBuilder.header("Content-Length", 0).put(Entity.entity("" + + + "", MediaType.APPLICATION_JSON)); + assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); + } + + @Test + void testBadOrderParticipantReport() throws PfModelException { + var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + + "/" + + UUID.randomUUID()); + var response = invocationBuilder.header("Content-Length", 0).put(Entity.entity("" + + + "", MediaType.APPLICATION_JSON)); + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); + } + + @Test + void testOrderAllParticipantReport() { + inputParticipants.forEach(p -> { + participantProvider.saveParticipant(p); + }); + var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT); + var response = invocationBuilder.header("Content-Length", 0).put(Entity.entity("" + + + "", MediaType.APPLICATION_JSON)); + assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); + } +} diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java index 9e35f2cf5..f7c18b67b 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandlerTest.java @@ -41,7 +41,7 @@ import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier; class SupervisionParticipantHandlerTest { private static final ToscaConceptIdentifier PARTICIPANT_ID = new ToscaConceptIdentifier("ParticipantId", "1.0.0"); private static final ToscaConceptIdentifier PARTICIPANT_TYPE = - new ToscaConceptIdentifier("ParticipantType", "1.0.0"); + new ToscaConceptIdentifier("ParticipantType", "1.0.0"); @Test void testHandleParticipantDeregister() { @@ -59,11 +59,11 @@ class SupervisionParticipantHandlerTest { participantDeregisterMessage.setParticipantType(PARTICIPANT_TYPE); var participantDeregisterAckPublisher = mock(ParticipantDeregisterAckPublisher.class); var handler = new SupervisionParticipantHandler(participantProvider, - mock(ParticipantRegisterAckPublisher.class), participantDeregisterAckPublisher); + mock(ParticipantRegisterAckPublisher.class), participantDeregisterAckPublisher); handler.handleParticipantMessage(participantDeregisterMessage); - verify(participantProvider).saveParticipant(any()); + verify(participantProvider).updateParticipant(any()); verify(participantDeregisterAckPublisher).send(participantDeregisterMessage.getMessageId()); } @@ -81,13 +81,13 @@ class SupervisionParticipantHandlerTest { var participantProvider = mock(ParticipantProvider.class); var participantRegisterAckPublisher = mock(ParticipantRegisterAckPublisher.class); var handler = new SupervisionParticipantHandler(participantProvider, participantRegisterAckPublisher, - mock(ParticipantDeregisterAckPublisher.class)); + mock(ParticipantDeregisterAckPublisher.class)); handler.handleParticipantMessage(participantRegisterMessage); verify(participantProvider).saveParticipant(any()); verify(participantRegisterAckPublisher).send(participantRegisterMessage.getMessageId(), PARTICIPANT_ID, - PARTICIPANT_TYPE); + PARTICIPANT_TYPE); } @Test @@ -99,7 +99,7 @@ class SupervisionParticipantHandlerTest { var participantProvider = mock(ParticipantProvider.class); var handler = new SupervisionParticipantHandler(participantProvider, - mock(ParticipantRegisterAckPublisher.class), mock(ParticipantDeregisterAckPublisher.class)); + mock(ParticipantRegisterAckPublisher.class), mock(ParticipantDeregisterAckPublisher.class)); handler.handleParticipantMessage(participantStatusMessage); verify(participantProvider).saveParticipant(any()); diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java index 0142f294c..1e07ec9cf 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionScannerTest.java @@ -61,7 +61,7 @@ class SupervisionScannerTest { private static UUID compositionId; private static final ToscaConceptIdentifier PARTICIPANT_TYPE = - new ToscaConceptIdentifier("org.onap.policy.clamp.acm.PolicyParticipant", PARTICIPANT_VERSION); + new ToscaConceptIdentifier("org.onap.policy.clamp.acm.PolicyParticipant", PARTICIPANT_VERSION); @BeforeAll public static void setUpBeforeAll() { @@ -83,11 +83,11 @@ class SupervisionScannerTest { var automationComposition = InstantiationUtils.getAutomationCompositionFromResource(AC_JSON, "Crud"); when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId)) - .thenReturn(List.of(automationComposition)); + .thenReturn(List.of(automationComposition)); var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider, - automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, - acRuntimeParameterGroup); + automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, + acRuntimeParameterGroup); supervisionScanner.run(false); verify(automationCompositionProvider, times(0)).updateAutomationComposition(any(AutomationComposition.class)); @@ -100,7 +100,7 @@ class SupervisionScannerTest { automationComposition.setOrderedState(AutomationCompositionOrderedState.UNINITIALISED); var automationCompositionProvider = mock(AutomationCompositionProvider.class); when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId)) - .thenReturn(List.of(automationComposition)); + .thenReturn(List.of(automationComposition)); var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class); var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); @@ -108,8 +108,8 @@ class SupervisionScannerTest { var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider, - automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, - acRuntimeParameterGroup); + automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, + acRuntimeParameterGroup); supervisionScanner.run(false); verify(automationCompositionProvider, times(1)).updateAutomationComposition(any(AutomationComposition.class)); @@ -120,7 +120,7 @@ class SupervisionScannerTest { var automationCompositionProvider = mock(AutomationCompositionProvider.class); var automationComposition = new AutomationComposition(); when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId)) - .thenReturn(List.of(automationComposition)); + .thenReturn(List.of(automationComposition)); var participantProvider = mock(ParticipantProvider.class); var participant = new Participant(); @@ -133,8 +133,8 @@ class SupervisionScannerTest { var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider, - automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, - acRuntimeParameterGroup); + automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, + acRuntimeParameterGroup); supervisionScanner.handleParticipantStatus(participant.getKey().asIdentifier()); supervisionScanner.run(true); @@ -148,7 +148,7 @@ class SupervisionScannerTest { automationComposition.setOrderedState(AutomationCompositionOrderedState.PASSIVE); for (var element : automationComposition.getElements().values()) { if ("org.onap.domain.database.Http_PMSHMicroserviceAutomationCompositionElement" - .equals(element.getDefinition().getName())) { + .equals(element.getDefinition().getName())) { element.setOrderedState(AutomationCompositionOrderedState.PASSIVE); element.setState(AutomationCompositionState.UNINITIALISED); } else { @@ -159,7 +159,7 @@ class SupervisionScannerTest { var automationCompositionProvider = mock(AutomationCompositionProvider.class); when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId)) - .thenReturn(List.of(automationComposition)); + .thenReturn(List.of(automationComposition)); var participantProvider = mock(ParticipantProvider.class); var automationCompositionUpdatePublisher = mock(AutomationCompositionUpdatePublisher.class); @@ -167,8 +167,8 @@ class SupervisionScannerTest { var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanner"); var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider, - automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, - acRuntimeParameterGroup); + automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, + acRuntimeParameterGroup); supervisionScanner.run(false); @@ -180,7 +180,7 @@ class SupervisionScannerTest { var automationCompositionProvider = mock(AutomationCompositionProvider.class); var automationComposition = new AutomationComposition(); when(automationCompositionProvider.getAcInstancesByCompositionId(compositionId)) - .thenReturn(List.of(automationComposition)); + .thenReturn(List.of(automationComposition)); var acRuntimeParameterGroup = CommonTestData.geParameterGroup("dbScanParticipant"); acRuntimeParameterGroup.getParticipantParameters().getUpdateParameters().setMaxWaitMs(-1); @@ -199,14 +199,14 @@ class SupervisionScannerTest { var automationCompositionStateChangePublisher = mock(AutomationCompositionStateChangePublisher.class); var supervisionScanner = new SupervisionScanner(automationCompositionProvider, acDefinitionProvider, - automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, - acRuntimeParameterGroup); + automationCompositionStateChangePublisher, automationCompositionUpdatePublisher, participantProvider, + acRuntimeParameterGroup); supervisionScanner.handleParticipantStatus(participant.getKey().asIdentifier()); supervisionScanner.run(true); - verify(participantProvider, times(0)).saveParticipant(any()); + verify(participantProvider, times(0)).updateParticipant(any()); supervisionScanner.run(true); - verify(participantProvider, times(1)).saveParticipant(any()); + verify(participantProvider, times(1)).updateParticipant(any()); } } diff --git a/runtime-acm/src/test/resources/providers/TestParticipant.json b/runtime-acm/src/test/resources/providers/TestParticipant.json new file mode 100644 index 000000000..fe06ba091 --- /dev/null +++ b/runtime-acm/src/test/resources/providers/TestParticipant.json @@ -0,0 +1,15 @@ +{ + "name": "dummy_participant1", + "version": "1.0.1", + "definition": { + "name": "org.onap.domain.pmsh.PMSHAutomationCompositionDefinition", + "version": "1.0.0" + }, + "participantState": "ON_LINE", + "description": "A dummy PMSH participant1", + "participantId": "82fd8ef9-1d1e-4343-9b28-7f9564ee3de6", + "participantType": { + "name": "org.onap.domain.pmsh.PolicyAutomationCompositionDefinition", + "version": "1.0.0" + } +} diff --git a/runtime-acm/src/test/resources/providers/TestParticipant2.json b/runtime-acm/src/test/resources/providers/TestParticipant2.json new file mode 100644 index 000000000..9a341844a --- /dev/null +++ b/runtime-acm/src/test/resources/providers/TestParticipant2.json @@ -0,0 +1,15 @@ +{ + "name": "dummy_participant2", + "version": "1.0.1", + "definition": { + "name": "org.onap.domain.pmsh.PMSHAutomationCompositionDefinition2", + "version": "1.0.0" + }, + "participantState": "ON_LINE", + "description": "A dummy PMSH participant2", + "participantId": "cac01d0a-7ba8-4dda-b9be-6983c46c0546", + "participantType": { + "name": "org.onap.domain.pmsh.PolicyAutomationCompositionDefinition2", + "version": "1.0.0" + } +} |