diff options
author | FrancescoFioraEst <francesco.fiora@est.tech> | 2023-06-13 09:19:08 +0100 |
---|---|---|
committer | Liam Fallon <liam.fallon@est.tech> | 2023-06-13 21:38:47 +0000 |
commit | 444d286f337a6d067e0b7db92da61cc478d840bc (patch) | |
tree | a788c425270675b6f29179210e1f0439a91b072b | |
parent | d25a6d199dc55ee9cc59b8c9b76e74f1a61ef6b6 (diff) |
Add Java Implementation for mock participant in ACM
Add Java Code Implementation for mock participant
to test different ACM scenarios.
Issue-ID: POLICY-4722
Change-Id: I8475c05c2469e190ca81d4caff0babc22c5d6db9
Signed-off-by: FrancescoFioraEst <francesco.fiora@est.tech>
(cherry picked from commit 73a48d9c7e599baf145820d0bc0968040142dac8)
17 files changed, 1713 insertions, 0 deletions
diff --git a/participant/participant-impl/participant-impl-simulator/pom.xml b/participant/participant-impl/participant-impl-simulator/pom.xml index da5b7632e..2fd8c3703 100644 --- a/participant/participant-impl/participant-impl-simulator/pom.xml +++ b/participant/participant-impl/participant-impl-simulator/pom.xml @@ -34,6 +34,38 @@ <build> <plugins> <plugin> + <groupId>io.swagger.codegen.v3</groupId> + <artifactId>swagger-codegen-maven-plugin</artifactId> + <executions> + <execution> + <id>code-gen</id> + <goals> + <goal>generate</goal> + </goals> + <configuration> + <inputSpec>${project.basedir}/src/main/resources/openapi/openapi.yaml</inputSpec> + <invokerPackage>org.onap.policy.clamp.acm.participant.sim.controller</invokerPackage> + <apiPackage>org.onap.policy.clamp.acm.participant.sim.controller.genapi</apiPackage> + <language>spring</language> + <generateModels>false</generateModels> + <generateSupportingFiles>false</generateSupportingFiles> + <importMappings> + AutomationCompositions=org.onap.policy.clamp.models.acm.concepts.AutomationCompositions, + InternalDatas=org.onap.policy.clamp.acm.participant.sim.model.InternalDatas, + InternalData=org.onap.policy.clamp.acm.participant.sim.model.InternalData, + SimConfig=org.onap.policy.clamp.acm.participant.sim.model.SimConfig + </importMappings> + <configOptions> + <sourceFolder>src/gen/java</sourceFolder> + <dateLibrary>java11</dateLibrary> + <interfaceOnly>true</interfaceOnly> + <useTags>true</useTags> + </configOptions> + </configuration> + </execution> + </executions> + </plugin> + <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <executions> diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/FilterConfig.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/FilterConfig.java new file mode 100644 index 000000000..b685970eb --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/FilterConfig.java @@ -0,0 +1,44 @@ +/*- + * ============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.participant.sim.config; + +import org.onap.policy.clamp.common.acm.rest.RequestResponseLoggingFilter; +import org.springframework.boot.web.servlet.FilterRegistrationBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class FilterConfig { + + /** + * Logging Filter configuration. + * + * @return FilterRegistrationBean + */ + @Bean + public FilterRegistrationBean<RequestResponseLoggingFilter> loggingFilter() { + FilterRegistrationBean<RequestResponseLoggingFilter> registrationBean = new FilterRegistrationBean<>(); + + registrationBean.setFilter(new RequestResponseLoggingFilter()); + registrationBean.addUrlPatterns("/onap/policy/clamp/acm/simparticipant/v2/*"); + return registrationBean; + } +} diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/MicrometerConfig.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/MicrometerConfig.java new file mode 100644 index 000000000..2a319c3bd --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/MicrometerConfig.java @@ -0,0 +1,46 @@ +/*- + * ============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.participant.sim.config; + +import io.micrometer.core.aop.TimedAspect; +import io.micrometer.core.instrument.MeterRegistry; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.config.BeanPostProcessor; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class MicrometerConfig { + + /** + * Load up the metrics registry. + */ + @Bean + public InitializingBean forcePrometheusPostProcessor(BeanPostProcessor meterRegistryPostProcessor, + MeterRegistry registry) { + return () -> meterRegistryPostProcessor.postProcessAfterInitialization(registry, ""); + } + + @Bean + public TimedAspect timedAspect(MeterRegistry registry) { + return new TimedAspect(registry); + } +} diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/SecurityConfig.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/SecurityConfig.java new file mode 100644 index 000000000..f15491c4d --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/SecurityConfig.java @@ -0,0 +1,49 @@ +/*- + * ============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.participant.sim.config; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.web.SecurityFilterChain; + +/** + * Configure how access to this module's REST end points is secured. + */ +@Configuration +public class SecurityConfig { + /** + * Return the configuration of how access to this module's REST end points is secured. + * + * @param http the HTTP security settings + * @return the HTTP security settings + */ + @Bean + public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception { + http + .httpBasic() + .and() + .authorizeHttpRequests().anyRequest().authenticated() + .and() + .csrf().disable(); + return http.build(); + } +} diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/SpringDocBean.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/SpringDocBean.java new file mode 100644 index 000000000..7bf1d1def --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/config/SpringDocBean.java @@ -0,0 +1,48 @@ +/*- + * ============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.participant.sim.config; + +import io.swagger.v3.oas.models.ExternalDocumentation; +import io.swagger.v3.oas.models.OpenAPI; +import io.swagger.v3.oas.models.info.Info; +import io.swagger.v3.oas.models.info.License; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class SpringDocBean { + + /** + * Bean to configure Springdoc. + * + * @return the OpenAPI specification + */ + @Bean + public OpenAPI acmElementParticipantOpenApi() { + return new OpenAPI() + .info(new Info().title("ACM Mock Participant") + .description("CLAMP Mock Participant API") + .license(new License().name("Apache 2.0").url("http://www.apache.org/licenses/LICENSE-2.0"))) + .externalDocs(new ExternalDocumentation() + .description("CLAMP Automation Composition Management Documentation") + .url("https://docs.onap.org/projects/onap-policy-parent/en/latest/clamp/clamp.html")); + } +} diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java new file mode 100644 index 000000000..7554c0b3c --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandler.java @@ -0,0 +1,290 @@ +/*- + * ============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.participant.sim.main.handler; + +import java.lang.invoke.MethodHandles; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import lombok.Getter; +import lombok.RequiredArgsConstructor; +import lombok.Setter; +import org.onap.policy.clamp.acm.participant.intermediary.api.AutomationCompositionElementListener; +import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; +import org.onap.policy.clamp.acm.participant.sim.model.InternalData; +import org.onap.policy.clamp.acm.participant.sim.model.InternalDatas; +import org.onap.policy.clamp.acm.participant.sim.model.SimConfig; +import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElementDefinition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions; +import org.onap.policy.clamp.models.acm.concepts.DeployState; +import org.onap.policy.clamp.models.acm.concepts.LockState; +import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.models.base.PfModelException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.stereotype.Component; + +/** + * This class handles implementation of automationCompositionElement updates. + */ +@Component +@RequiredArgsConstructor +public class AutomationCompositionElementHandler implements AutomationCompositionElementListener { + + private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + private final ParticipantIntermediaryApi intermediaryApi; + + @Getter + @Setter + private SimConfig config = new SimConfig(); + + /** + * Callback method to handle an update on a automation composition element. + * + * @param automationCompositionId the automationComposition Id + * @param element the information on the automation composition element + * @param properties properties Map + * @throws PfModelException in case of a exception + */ + @Override + public void deploy(UUID automationCompositionId, AcElementDeploy element, Map<String, Object> properties) + throws PfModelException { + LOGGER.debug("deploy call"); + + if (!execution(config.getDeployTimerMs(), "Current Thread deploy is Interrupted during execution {}", + element.getId())) { + return; + } + + if (config.isDeploySuccess()) { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); + } else { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!"); + } + } + + private boolean execution(int timeMs, String msg, UUID elementId) { + long endTime = System.currentTimeMillis() + timeMs; + while (System.currentTimeMillis() < endTime) { + try { + if (Thread.currentThread().isInterrupted()) { + LOGGER.debug(msg, elementId); + return false; + } + Thread.sleep(10L); + } catch (InterruptedException e) { + LOGGER.debug(msg, elementId); + Thread.currentThread().interrupt(); + return false; + } + } + return true; + } + + /** + * Handle a automation composition element state change. + * + * @param automationCompositionElementId the ID of the automation composition element + */ + @Override + public void undeploy(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException { + LOGGER.debug("undeploy call"); + + if (!execution(config.getUndeployTimerMs(), "Current Thread undeploy is Interrupted during execution {}", + automationCompositionElementId)) { + return; + } + + if (config.isUndeploySuccess()) { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, + automationCompositionElementId, DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR, + "Undeployed"); + } else { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, + automationCompositionElementId, DeployState.DEPLOYED, null, StateChangeResult.FAILED, + "Undeploy failed!"); + } + } + + @Override + public void lock(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException { + LOGGER.debug("lock call"); + + if (!execution(config.getLockTimerMs(), "Current Thread lock is Interrupted during execution {}", + automationCompositionElementId)) { + return; + } + + if (config.isLockSuccess()) { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, + automationCompositionElementId, null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked"); + } else { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, + automationCompositionElementId, null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!"); + } + } + + @Override + public void unlock(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException { + LOGGER.debug("unlock call"); + + if (!execution(config.getUnlockTimerMs(), "Current Thread unlock is Interrupted during execution {}", + automationCompositionElementId)) { + return; + } + + if (config.isUnlockSuccess()) { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, + automationCompositionElementId, null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked"); + } else { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, + automationCompositionElementId, null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!"); + } + } + + @Override + public void delete(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException { + LOGGER.debug("delete call"); + + if (!execution(config.getDeleteTimerMs(), "Current Thread delete is Interrupted during execution {}", + automationCompositionElementId)) { + return; + } + + if (config.isDeleteSuccess()) { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, + automationCompositionElementId, DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted"); + } else { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, + automationCompositionElementId, DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, + "Delete failed!"); + } + } + + @Override + public void update(UUID automationCompositionId, AcElementDeploy element, Map<String, Object> properties) + throws PfModelException { + LOGGER.debug("updat call"); + + if (!execution(config.getUpdateTimerMs(), "Current Thread update is Interrupted during execution {}", + element.getId())) { + return; + } + + if (config.isUpdateSuccess()) { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated"); + } else { + intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(), + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!"); + } + } + + /** + * Get AutomationComposition. + * + * @return the AutomationCompositions + */ + public AutomationCompositions getAutomationCompositions() { + var result = new AutomationCompositions(); + result.setAutomationCompositionList(new ArrayList<>(intermediaryApi.getAutomationCompositions().values())); + return result; + } + + /** + * Set OutProperties. + * + * @param automationCompositionId the automationComposition Id + * @param elementId the automationComposition Element Id + * @param useState the useState + * @param operationalState the operationalState + * @param outProperties the outProperties + */ + public void setOutProperties(UUID automationCompositionId, UUID elementId, String useState, String operationalState, + Map<String, Object> outProperties) { + intermediaryApi.sendAcElementInfo(automationCompositionId, elementId, useState, operationalState, + outProperties); + } + + @Override + public void prime(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList) + throws PfModelException { + + if (!execution(config.getPrimeTimerMs(), "Current Thread prime is Interrupted during execution {}", + compositionId)) { + return; + } + + if (config.isPrimeSuccess()) { + intermediaryApi.updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, + "Primed"); + } else { + intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.FAILED, + "Prime failed!"); + } + } + + @Override + public void deprime(UUID compositionId) throws PfModelException { + + if (!execution(config.getDeprimeTimerMs(), "Current Thread deprime is Interrupted during execution {}", + compositionId)) { + return; + } + + if (config.isDeprimeSuccess()) { + intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR, + "Deprimed"); + } else { + intermediaryApi.updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.FAILED, + "Deprime failed!"); + } + } + + /** + * Get Data List. + * + * @return the InternalDatas + */ + public InternalDatas getDataList() { + var result = new InternalDatas(); + var map = intermediaryApi.getAutomationCompositions(); + for (var instance : map.values()) { + for (var element : instance.getElements().values()) { + var data = new InternalData(); + data.setAutomationCompositionId(instance.getInstanceId()); + data.setAutomationCompositionElementId(element.getId()); + data.setIntProperties(element.getProperties()); + data.setOperationalState(element.getOperationalState()); + data.setUseState(element.getUseState()); + data.setOutProperties(element.getOutProperties()); + result.getList().add(data); + } + } + return result; + } +} diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/InternalData.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/InternalData.java new file mode 100644 index 000000000..14e53338d --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/InternalData.java @@ -0,0 +1,36 @@ +/*- + * ============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.participant.sim.model; + +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.UUID; +import lombok.Data; + +@Data +public class InternalData { + Map<String, Object> intProperties = new LinkedHashMap<>(); + Map<String, Object> outProperties = new LinkedHashMap<>(); + UUID automationCompositionId; + UUID automationCompositionElementId; + String useState; + String operationalState; +} diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/InternalDatas.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/InternalDatas.java new file mode 100644 index 000000000..ca7844657 --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/InternalDatas.java @@ -0,0 +1,31 @@ +/*- + * ============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.participant.sim.model; + +import java.util.ArrayList; +import java.util.List; +import lombok.Data; + +@Data +public class InternalDatas { + + List<InternalData> list = new ArrayList<>(); +} diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java new file mode 100644 index 000000000..cf216c1e8 --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java @@ -0,0 +1,58 @@ +/*- + * ============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.participant.sim.model; + +import lombok.Data; + +@Data +public class SimConfig { + private boolean deploySuccess = true; + + private boolean undeploySuccess = true; + + private boolean lockSuccess = true; + + private boolean unlockSuccess = true; + + private boolean deleteSuccess = true; + + private boolean updateSuccess = true; + + private boolean primeSuccess = true; + + private boolean deprimeSuccess = true; + + private int deployTimerMs = 1000; + + private int undeployTimerMs = 1000; + + private int lockTimerMs = 100; + + private int unlockTimerMs = 100; + + private int updateTimerMs = 100; + + private int deleteTimerMs = 100; + + private int primeTimerMs = 100; + + private int deprimeTimerMs = 100; +} diff --git a/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/rest/SimulatorController.java b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/rest/SimulatorController.java new file mode 100644 index 000000000..a12e5f70d --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/rest/SimulatorController.java @@ -0,0 +1,80 @@ +/*- + * ============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.participant.sim.rest; + +import java.util.UUID; +import javax.validation.Valid; +import javax.ws.rs.core.MediaType; +import lombok.RequiredArgsConstructor; +import org.onap.policy.clamp.acm.participant.sim.controller.genapi.SimulatorParticipantControllerApi; +import org.onap.policy.clamp.acm.participant.sim.main.handler.AutomationCompositionElementHandler; +import org.onap.policy.clamp.acm.participant.sim.model.InternalData; +import org.onap.policy.clamp.acm.participant.sim.model.InternalDatas; +import org.onap.policy.clamp.acm.participant.sim.model.SimConfig; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions; +import org.springframework.http.HttpStatus; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RequiredArgsConstructor +@RestController +@RequestMapping(value = "/v2", produces = {MediaType.APPLICATION_JSON}) +public class SimulatorController implements SimulatorParticipantControllerApi { + + private final AutomationCompositionElementHandler automationCompositionElementHandler; + + @Override + public ResponseEntity<SimConfig> getConfig(UUID xonapRequestId) { + return new ResponseEntity<>(automationCompositionElementHandler.getConfig(), HttpStatus.OK); + } + + @Override + public ResponseEntity<Void> setConfig(UUID xonapRequestId, @Valid @RequestBody SimConfig body) { + automationCompositionElementHandler.setConfig(body); + return new ResponseEntity<>(HttpStatus.OK); + } + + @Override + public ResponseEntity<AutomationCompositions> getAutomationCompositions(UUID xonapRequestId) { + return new ResponseEntity<>(automationCompositionElementHandler.getAutomationCompositions(), HttpStatus.OK); + } + + @Override + public ResponseEntity<InternalDatas> getDatas(UUID xonapRequestId) { + return new ResponseEntity<>(automationCompositionElementHandler.getDataList(), HttpStatus.OK); + } + + /** + * Set Data. + * + * @param body the Data + * @return Void + */ + @Override + public ResponseEntity<Void> setData(UUID xonapRequestId, @Valid @RequestBody InternalData body) { + automationCompositionElementHandler.setOutProperties(body.getAutomationCompositionId(), + body.getAutomationCompositionElementId(), body.getUseState(), body.getOperationalState(), + body.getOutProperties()); + return new ResponseEntity<>(HttpStatus.OK); + } +} diff --git a/participant/participant-impl/participant-impl-simulator/src/main/resources/openapi/openapi.yaml b/participant/participant-impl/participant-impl-simulator/src/main/resources/openapi/openapi.yaml new file mode 100644 index 000000000..b95aa33cd --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/main/resources/openapi/openapi.yaml @@ -0,0 +1,339 @@ +openapi: 3.0.3 +info: + title: ACM Simulator Participant + description: CLAMP Automation Composition Management Simulator Participant API + contact: + name: ONAP Support + url: https://lists.onap.org/g/onap-discuss + email: onap-discuss@lists.onap.org + license: + name: Apache 2.0 + url: http://www.apache.org/licenses/LICENSE-2.0 + version: '1.0' +externalDocs: + description: CLAMP Automation Composition Management Documentation + url: https://docs.onap.org/projects/onap-policy-parent/en/latest/clamp/clamp.html +tags: + - name: Simulator-participant-controller + description: Automation Composition Element Test Participant controller +servers: + - url: http:{port}/{server} + variables: + port: + default: "8084" + description: This value is assigned by the service provider + server: + default: /onap/policy/clamp/acm/simparticipant + description: This value is assigned by the service provider +paths: + /parameters: + get: + tags: + - Simulator-participant-controller + summary: Return all Parameters + description: Return all the parameters configured in the Simulator Participant + operationId: getConfig + parameters: + - name: X-onap-RequestId + in: header + description: RequestID for http transaction + schema: + type: string + format: uuid + responses: + 200: + description: OK, reutrns a serialised instance of + [SimConfig](https://github.com/onap/policy-clamp/blob/master/participant/participant-impl/policy-clamp-participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java) + headers: + api-version: + schema: + type: string + X-LatestVersion: + schema: + type: string + description: Used only to communicate an API's latest version + X-PatchVersion: + schema: + type: string + description: + Used only to communicate a PATCH version in a response for troubleshooting purposes only, + and will not be provided by the client on request + X-MinorVersion: + schema: + type: string + description: + Used to request or communicate a MINOR version back from the client + to the server, and from the server back to the client + X-onap-RequestId: + schema: + type: string + format: uuid + description: Used to track REST transactions for logging purposes + content: + application/json: + schema: + $ref: '#/components/schemas/SimConfig' + application/yaml: + schema: + $ref: '#/components/schemas/SimConfig' + 401: + description: Authorization Error + 500: + description: Internal Server Error + security: + - basicAuth: [] + put: + tags: + - Simulator-participant-controller + summary: change the parameters + description: >- + Change the parameters the behaviour of the Simulator Participant + operationId: setConfig + parameters: + - name: X-ONAP-RequestID + in: header + description: RequestID for http transaction + required: false + schema: + type: string + format: uuid + requestBody: + description: The information for the behaviour in a serialised instance of + [SimConfig](https://github.com/onap/policy-clamp/blob/master/participant/participant-impl/policy-clamp-participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/SimConfig.java) + content: + application/json: + schema: + $ref: '#/components/schemas/SimConfig' + application/yaml: + schema: + $ref: '#/components/schemas/SimConfig' + responses: + 200: + description: OK, the parameters has been saved + headers: + api-version: + schema: + type: string + X-LatestVersion: + schema: + type: string + description: Used only to communicate an API's latest version + X-PatchVersion: + schema: + type: string + description: + Used only to communicate a PATCH version in a response for troubleshooting purposes only, + and will not be provided by the client on request + X-MinorVersion: + schema: + type: string + description: + Used to request or communicate a MINOR version back from the client + to the server, and from the server back to the client + X-onap-RequestId: + schema: + type: string + format: uuid + description: Used to track REST transactions for logging purposes + 400: + description: Bad Request + 401: + description: Authorization Error + 500: + description: Internal Server Error + security: + - basicAuth: [] + /instances: + get: + tags: + - Simulator-participant-controller + summary: Query details of the requested automation composition instances + description: Query details of the requested automation composition instances for the given automation composition definition ID, returning + details of all its automation composition instances + operationId: getAutomationCompositions + parameters: + - name: X-onap-RequestId + in: header + description: RequestID for http transaction + schema: + type: string + format: uuid + responses: + 200: + description: Serialised instance of + [AutomationCompositions](https://github.com/onap/policy-clamp/blob/master/models/src/main/java/org/onap/policy/clamp/models/acm/concepts/AutomationCompositions.java) + containing a list of automation composition instances found + headers: + api-version: + schema: + type: string + X-LatestVersion: + schema: + type: string + description: Used only to communicate an API's latest version + X-PatchVersion: + schema: + type: string + description: + Used only to communicate a PATCH version in a response for troubleshooting purposes only, + and will not be provided by the client on request + X-MinorVersion: + schema: + type: string + description: + Used to request or communicate a MINOR version back from the client + to the server, and from the server back to the client + X-onap-RequestId: + schema: + type: string + format: uuid + description: Used to track REST transactions for logging purposes + content: + application/json: + schema: + $ref: '#/components/schemas/AutomationCompositions' + application/yaml: + schema: + $ref: '#/components/schemas/AutomationCompositions' + 401: + description: Authorization Error + 500: + description: Internal Server Error + security: + - basicAuth: [] + /datas: + get: + tags: + - Simulator-participant-controller + summary: Query details of the requested internal datas + description: Query details of the requested internal datas + operationId: getDatas + parameters: + - name: X-onap-RequestId + in: header + description: RequestID for http transaction + schema: + type: string + format: uuid + responses: + 200: + description: Serialised instance of + [InternalDatas](https://github.com/onap/policy-clamp/blob/master/participant/participant-impl/policy-clamp-participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/InternalDatas.java) + headers: + api-version: + schema: + type: string + X-LatestVersion: + schema: + type: string + description: Used only to communicate an API's latest version + X-PatchVersion: + schema: + type: string + description: + Used only to communicate a PATCH version in a response for troubleshooting purposes only, + and will not be provided by the client on request + X-MinorVersion: + schema: + type: string + description: + Used to request or communicate a MINOR version back from the client + to the server, and from the server back to the client + X-onap-RequestId: + schema: + type: string + format: uuid + description: Used to track REST transactions for logging purposes + content: + application/json: + schema: + $ref: '#/components/schemas/InternalDatas' + application/yaml: + schema: + $ref: '#/components/schemas/InternalDatas' + 401: + description: Authorization Error + 500: + description: Internal Server Error + security: + - basicAuth: [] + put: + tags: + - Simulator-participant-controller + summary: change the parameters + description: >- + Change the data of the Simulator Participant + operationId: setData + parameters: + - name: X-ONAP-RequestID + in: header + description: RequestID for http transaction + required: false + schema: + type: string + format: uuid + requestBody: + description: The data in a serialised instance of + [InternalData](https://github.com/onap/policy-clamp/blob/master/participant/participant-impl/policy-clamp-participant-impl-simulator/src/main/java/org/onap/policy/clamp/acm/participant/sim/model/InternalData.java) + content: + application/json: + schema: + $ref: '#/components/schemas/InternalData' + application/yaml: + schema: + $ref: '#/components/schemas/InternalData' + responses: + 200: + description: OK, the data has been saved + headers: + api-version: + schema: + type: string + X-LatestVersion: + schema: + type: string + description: Used only to communicate an API's latest version + X-PatchVersion: + schema: + type: string + description: + Used only to communicate a PATCH version in a response for troubleshooting purposes only, + and will not be provided by the client on request + X-MinorVersion: + schema: + type: string + description: + Used to request or communicate a MINOR version back from the client + to the server, and from the server back to the client + X-onap-RequestId: + schema: + type: string + format: uuid + description: Used to track REST transactions for logging purposes + 400: + description: Bad Request + 401: + description: Authorization Error + 500: + description: Internal Server Error + security: + - basicAuth: [] + +components: + securitySchemes: + basicAuth: + type: http + scheme: basic + schemas: + SimConfig: + title: SimConfig + type: object + AutomationCompositions: + title: AutomationCompositions + type: object + InternalDatas: + title: InternalDatas + type: object + InternalData: + title: InternalData + type: object diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/comm/CommonTestData.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/comm/CommonTestData.java index c2338d9fe..ee86b8f88 100644 --- a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/comm/CommonTestData.java +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/comm/CommonTestData.java @@ -26,6 +26,8 @@ import java.util.Map; import java.util.TreeMap; import java.util.UUID; import org.onap.policy.clamp.acm.participant.sim.parameters.ParticipantSimParameters; +import org.onap.policy.clamp.models.acm.concepts.AutomationComposition; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.common.endpoints.parameters.TopicParameters; import org.onap.policy.common.utils.coder.Coder; import org.onap.policy.common.utils.coder.CoderException; @@ -112,4 +114,32 @@ public class CommonTestData { public static UUID getParticipantId() { return UUID.fromString("101c62b3-8918-41b9-a747-d21eb79c6c01"); } + + /** + * Returns a Map of ToscaConceptIdentifier and AutomationComposition for test cases. + * + * @return automationCompositionMap + * + * @throws CoderException if there is an error with .json file. + */ + public static Map<UUID, AutomationComposition> getTestAutomationCompositionMap() { + var automationComposition = getTestAutomationComposition(); + return Map.of(automationComposition.getInstanceId(), automationComposition); + } + + /** + * Returns List of AutomationComposition for test cases. + * + * @return AutomationCompositions + * + * @throws CoderException if there is an error with .json file. + */ + public static AutomationComposition getTestAutomationComposition() { + var automationComposition = new AutomationComposition(); + automationComposition.setInstanceId(UUID.randomUUID()); + var element = new AutomationCompositionElement(); + element.setId(UUID.randomUUID()); + automationComposition.setElements(Map.of(element.getId(), element)); + return automationComposition; + } } diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java new file mode 100644 index 000000000..977b9d8e4 --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/main/handler/AutomationCompositionElementHandlerTest.java @@ -0,0 +1,236 @@ +/*- + * ============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.participant.sim.main.handler; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +import java.util.List; +import java.util.Map; +import java.util.UUID; +import org.junit.jupiter.api.Test; +import org.onap.policy.clamp.acm.participant.intermediary.api.ParticipantIntermediaryApi; +import org.onap.policy.clamp.acm.participant.sim.comm.CommonTestData; +import org.onap.policy.clamp.acm.participant.sim.model.SimConfig; +import org.onap.policy.clamp.models.acm.concepts.AcElementDeploy; +import org.onap.policy.clamp.models.acm.concepts.AcTypeState; +import org.onap.policy.clamp.models.acm.concepts.DeployState; +import org.onap.policy.clamp.models.acm.concepts.LockState; +import org.onap.policy.clamp.models.acm.concepts.StateChangeResult; +import org.onap.policy.models.base.PfModelException; + +class AutomationCompositionElementHandlerTest { + + @Test + void testDeploy() throws PfModelException { + var config = new SimConfig(); + config.setDeployTimerMs(1); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + acElementHandler.setConfig(config); + var instanceId = UUID.randomUUID(); + var element = new AcElementDeploy(); + element.setId(UUID.randomUUID()); + acElementHandler.deploy(instanceId, element, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed"); + + config.setDeploySuccess(false); + acElementHandler.deploy(instanceId, element, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!"); + } + + @Test + void testUndeploy() throws PfModelException { + var config = new SimConfig(); + config.setUndeployTimerMs(1); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + acElementHandler.setConfig(config); + var instanceId = UUID.randomUUID(); + var elementId = UUID.randomUUID(); + acElementHandler.undeploy(instanceId, elementId); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.UNDEPLOYED, + null, StateChangeResult.NO_ERROR, "Undeployed"); + + config.setUndeploySuccess(false); + acElementHandler.undeploy(instanceId, elementId); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.DEPLOYED, + null, StateChangeResult.FAILED, "Undeploy failed!"); + } + + @Test + void testLock() throws PfModelException { + var config = new SimConfig(); + config.setLockTimerMs(1); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + acElementHandler.setConfig(config); + var instanceId = UUID.randomUUID(); + var elementId = UUID.randomUUID(); + acElementHandler.lock(instanceId, elementId); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.LOCKED, + StateChangeResult.NO_ERROR, "Locked"); + + config.setLockSuccess(false); + acElementHandler.lock(instanceId, elementId); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.UNLOCKED, + StateChangeResult.FAILED, "Lock failed!"); + } + + @Test + void testUnlock() throws PfModelException { + var config = new SimConfig(); + config.setUnlockTimerMs(1); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + acElementHandler.setConfig(config); + var instanceId = UUID.randomUUID(); + var elementId = UUID.randomUUID(); + acElementHandler.unlock(instanceId, elementId); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.UNLOCKED, + StateChangeResult.NO_ERROR, "Unlocked"); + + config.setUnlockSuccess(false); + acElementHandler.unlock(instanceId, elementId); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, null, LockState.LOCKED, + StateChangeResult.FAILED, "Unlock failed!"); + } + + @Test + void testUpdate() throws PfModelException { + var config = new SimConfig(); + config.setUpdateTimerMs(1); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + acElementHandler.setConfig(config); + var instanceId = UUID.randomUUID(); + var element = new AcElementDeploy(); + element.setId(UUID.randomUUID()); + acElementHandler.update(instanceId, element, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated"); + + config.setUpdateSuccess(false); + acElementHandler.update(instanceId, element, Map.of()); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, element.getId(), + DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!"); + } + + @Test + void testDelete() throws PfModelException { + var config = new SimConfig(); + config.setDeleteTimerMs(1); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + acElementHandler.setConfig(config); + var instanceId = UUID.randomUUID(); + var elementId = UUID.randomUUID(); + acElementHandler.delete(instanceId, elementId); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.DELETED, + null, StateChangeResult.NO_ERROR, "Deleted"); + + config.setDeleteSuccess(false); + acElementHandler.delete(instanceId, elementId); + verify(intermediaryApi).updateAutomationCompositionElementState(instanceId, elementId, DeployState.UNDEPLOYED, + null, StateChangeResult.FAILED, "Delete failed!"); + } + + @Test + void testgetAutomationComposition() throws PfModelException { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + + var map = CommonTestData.getTestAutomationCompositionMap(); + when(intermediaryApi.getAutomationCompositions()).thenReturn(map); + var result = acElementHandler.getAutomationCompositions(); + assertEquals(map.values().iterator().next(), result.getAutomationCompositionList().get(0)); + } + + @Test + void testsetOutProperties() { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + + var instanceId = UUID.randomUUID(); + var elementId = UUID.randomUUID(); + var useState = "useState"; + var operationalState = "operationalState"; + Map<String, Object> map = Map.of("id", "1234"); + + acElementHandler.setOutProperties(instanceId, elementId, useState, operationalState, map); + verify(intermediaryApi).sendAcElementInfo(instanceId, elementId, useState, operationalState, map); + } + + @Test + void testgetDataList() { + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + + var map = CommonTestData.getTestAutomationCompositionMap(); + when(intermediaryApi.getAutomationCompositions()).thenReturn(map); + var result = acElementHandler.getDataList(); + var data = result.getList().get(0); + var autocomposition = map.values().iterator().next(); + assertEquals(autocomposition.getInstanceId(), data.getAutomationCompositionId()); + var element = autocomposition.getElements().values().iterator().next(); + assertEquals(element.getId(), data.getAutomationCompositionElementId()); + } + + @Test + void testPrime() throws PfModelException { + var config = new SimConfig(); + config.setPrimeTimerMs(1); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + acElementHandler.setConfig(config); + var compositionId = UUID.randomUUID(); + acElementHandler.prime(compositionId, List.of()); + verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR, + "Primed"); + + config.setPrimeSuccess(false); + acElementHandler.prime(compositionId, List.of()); + verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, + StateChangeResult.FAILED, "Prime failed!"); + } + + @Test + void testDeprime() throws PfModelException { + var config = new SimConfig(); + config.setDeprimeTimerMs(1); + var intermediaryApi = mock(ParticipantIntermediaryApi.class); + var acElementHandler = new AutomationCompositionElementHandler(intermediaryApi); + acElementHandler.setConfig(config); + var compositionId = UUID.randomUUID(); + acElementHandler.deprime(compositionId); + verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.COMMISSIONED, + StateChangeResult.NO_ERROR, "Deprimed"); + + config.setDeprimeSuccess(false); + acElementHandler.deprime(compositionId); + verify(intermediaryApi).updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.FAILED, + "Deprime failed!"); + } +} diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/rest/AcSimRestTest.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/rest/AcSimRestTest.java new file mode 100644 index 000000000..bcdabc86d --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/rest/AcSimRestTest.java @@ -0,0 +1,143 @@ +/*- + * ============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.participant.sim.rest; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.mockito.Mockito.doReturn; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; +import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; + +import java.util.UUID; +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.participant.sim.comm.CommonTestData; +import org.onap.policy.clamp.acm.participant.sim.main.handler.AutomationCompositionElementHandler; +import org.onap.policy.clamp.acm.participant.sim.model.InternalData; +import org.onap.policy.clamp.acm.participant.sim.model.InternalDatas; +import org.onap.policy.clamp.acm.participant.sim.model.SimConfig; +import org.onap.policy.clamp.acm.participant.sim.parameters.ParticipantSimParameters; +import org.onap.policy.clamp.models.acm.concepts.AutomationCompositions; +import org.onap.policy.common.utils.coder.Coder; +import org.onap.policy.common.utils.coder.StandardCoder; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration; +import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest; +import org.springframework.boot.test.mock.mockito.MockBean; +import org.springframework.context.annotation.Import; +import org.springframework.http.MediaType; +import org.springframework.test.context.junit.jupiter.SpringExtension; +import org.springframework.test.web.servlet.MockMvc; +import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; +import org.springframework.test.web.servlet.setup.MockMvcBuilders; +import org.springframework.web.context.WebApplicationContext; + +@ExtendWith(SpringExtension.class) +@WebMvcTest(value = SimulatorController.class) +@Import({MetricsAutoConfiguration.class, CompositeMeterRegistryAutoConfiguration.class}) +@EnableConfigurationProperties(value = ParticipantSimParameters.class) +class AcSimRestTest { + + private static final Coder CODER = new StandardCoder(); + private static final String CONFIG_URL = "/v2/parameters"; + private static final String INSTANCE_URL = "/v2/instances"; + private static final String DATAS_URL = "/v2/datas"; + + @Autowired + private MockMvc mockMvc; + + @MockBean + private AutomationCompositionElementHandler automationCompositionElementHandler; + + @Autowired + private WebApplicationContext context; + + @BeforeEach + void mockServiceClass() { + this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context).build(); + } + + @Test + void testgetConfig() throws Exception { + var requestBuilder = MockMvcRequestBuilders.get(CONFIG_URL).accept(MediaType.APPLICATION_JSON_VALUE); + + doReturn(new SimConfig()).when(automationCompositionElementHandler).getConfig(); + + mockMvc.perform(requestBuilder).andExpect(status().isOk()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)) + .andExpect(jsonPath("$.primeTimerMs", is(100))); + } + + @Test + void testsetConfig() throws Exception { + var requestBuilder = MockMvcRequestBuilders.put(CONFIG_URL).accept(MediaType.APPLICATION_JSON_VALUE) + .content(CODER.encode(new SimConfig())).contentType(MediaType.APPLICATION_JSON_VALUE); + + mockMvc.perform(requestBuilder).andExpect(status().isOk()); + } + + @Test + void testgetAutomationCompositions() throws Exception { + var requestBuilder = MockMvcRequestBuilders.get(INSTANCE_URL).accept(MediaType.APPLICATION_JSON_VALUE); + + var automationCompositions = new AutomationCompositions(); + automationCompositions.getAutomationCompositionList().add(CommonTestData.getTestAutomationComposition()); + + doReturn(automationCompositions).when(automationCompositionElementHandler).getAutomationCompositions(); + + var result = mockMvc.perform(requestBuilder).andExpect(status().isOk()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)).andReturn(); + var body = result.getResponse().getContentAsString(); + var acsResult = CODER.decode(body, AutomationCompositions.class); + assertEquals(automationCompositions.getAutomationCompositionList().get(0).getInstanceId(), + acsResult.getAutomationCompositionList().get(0).getInstanceId()); + } + + @Test + void testgetDatas() throws Exception { + var internalDatas = new InternalDatas(); + var internalData = new InternalData(); + internalData.setAutomationCompositionId(UUID.randomUUID()); + internalDatas.getList().add(internalData); + + doReturn(internalDatas).when(automationCompositionElementHandler).getDataList(); + + var requestBuilder = MockMvcRequestBuilders.get(DATAS_URL).accept(MediaType.APPLICATION_JSON_VALUE); + var result = mockMvc.perform(requestBuilder).andExpect(status().isOk()) + .andExpect(content().contentTypeCompatibleWith(MediaType.APPLICATION_JSON)).andReturn(); + var body = result.getResponse().getContentAsString(); + var acsResult = CODER.decode(body, InternalDatas.class); + assertEquals(internalData.getAutomationCompositionId(), + acsResult.getList().get(0).getAutomationCompositionId()); + } + + @Test + void testsetDatas() throws Exception { + var requestBuilder = MockMvcRequestBuilders.put(DATAS_URL).accept(MediaType.APPLICATION_JSON_VALUE) + .content(CODER.encode(new InternalData())).contentType(MediaType.APPLICATION_JSON_VALUE); + + mockMvc.perform(requestBuilder).andExpect(status().isOk()); + } +} diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/rest/ActuatorControllerTest.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/rest/ActuatorControllerTest.java new file mode 100644 index 000000000..474d45cc5 --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/rest/ActuatorControllerTest.java @@ -0,0 +1,92 @@ +/*- + * ============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.participant.sim.rest; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import javax.ws.rs.client.Invocation; +import javax.ws.rs.core.Response; +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.participant.sim.utils.CommonActuatorController; +import org.springframework.boot.test.autoconfigure.actuate.metrics.AutoConfigureMetrics; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.boot.test.context.SpringBootTest.WebEnvironment; +import org.springframework.boot.test.web.server.LocalServerPort; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit.jupiter.SpringExtension; + +@AutoConfigureMetrics +@ExtendWith(SpringExtension.class) +@SpringBootTest(webEnvironment = WebEnvironment.RANDOM_PORT) +@ActiveProfiles("test") +class ActuatorControllerTest extends CommonActuatorController { + + private static final String HEALTH_ENDPOINT = "health"; + private static final String METRICS_ENDPOINT = "metrics"; + private static final String PROMETHEUS_ENDPOINT = "prometheus"; + + @LocalServerPort + private int randomServerPort; + + @BeforeEach + public void setUpPort() { + super.setHttpPrefix(randomServerPort); + } + + @Test + void testGetHealth_Unauthorized() throws Exception { + assertUnauthorizedActGet(HEALTH_ENDPOINT); + } + + @Test + void testGetMetrics_Unauthorized() throws Exception { + assertUnauthorizedActGet(METRICS_ENDPOINT); + } + + @Test + void testGetPrometheus_Unauthorized() throws Exception { + assertUnauthorizedActGet(PROMETHEUS_ENDPOINT); + } + + @Test + void testGetHealth() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(HEALTH_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + + @Test + void testGetMetrics() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(METRICS_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + + @Test + void testGePrometheus() throws Exception { + Invocation.Builder invocationBuilder = super.sendActRequest(PROMETHEUS_ENDPOINT); + Response rawresp = invocationBuilder.buildGet().invoke(); + assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus()); + } + +} diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/utils/CommonActuatorController.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/utils/CommonActuatorController.java new file mode 100644 index 000000000..846e76349 --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/utils/CommonActuatorController.java @@ -0,0 +1,108 @@ +/*- + * ============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.participant.sim.utils; + +import static org.junit.Assert.assertEquals; + +import javax.ws.rs.client.Client; +import javax.ws.rs.client.ClientBuilder; +import javax.ws.rs.client.Invocation; +import javax.ws.rs.client.WebTarget; +import javax.ws.rs.core.MediaType; +import javax.ws.rs.core.Response; +import org.glassfish.jersey.client.ClientProperties; +import org.glassfish.jersey.client.authentication.HttpAuthenticationFeature; +import org.onap.policy.common.gson.GsonMessageBodyHandler; +import org.onap.policy.common.utils.network.NetworkUtil; + +/** + * Class to perform Rest unit tests. + * + */ +public class CommonActuatorController { + + public static final String SELF = NetworkUtil.getHostname(); + public static final String CONTEXT_PATH = "onap/policy/clamp/acm/simparticipant/"; + + private static String httpPrefix; + + /** + * Sends a request to an actuator endpoint. + * + * @param endpoint the target endpoint + * @return a request builder + */ + protected Invocation.Builder sendActRequest(final String endpoint) { + return sendFqeRequest(httpPrefix + CONTEXT_PATH + endpoint, true); + } + + /** + * Sends a request to an actuator endpoint, without any authorization header. + * + * @param endpoint the target endpoint + * @return a request builder + */ + protected Invocation.Builder sendNoAuthActRequest(final String endpoint) { + return sendFqeRequest(httpPrefix + CONTEXT_PATH + endpoint, false); + } + + /** + * Sends a request to a fully qualified endpoint. + * + * @param fullyQualifiedEndpoint the fully qualified target endpoint + * @param includeAuth if authorization header should be included + * @return a request builder + */ + protected Invocation.Builder sendFqeRequest(final String fullyQualifiedEndpoint, boolean includeAuth) { + final Client client = ClientBuilder.newBuilder().build(); + + client.property(ClientProperties.METAINF_SERVICES_LOOKUP_DISABLE, "true"); + client.register(GsonMessageBodyHandler.class); + + if (includeAuth) { + client.register(HttpAuthenticationFeature.basic("participantUser", "zb!XztG34")); + } + + final WebTarget webTarget = client.target(fullyQualifiedEndpoint); + + return webTarget.request(MediaType.APPLICATION_JSON, MediaType.TEXT_PLAIN); + } + + /** + * Assert that GET call to actuator endpoint is Unauthorized. + * + * @param endPoint the endpoint + */ + protected void assertUnauthorizedActGet(final String endPoint) { + Response rawresp = sendNoAuthActRequest(endPoint).buildGet().invoke(); + assertEquals(Response.Status.UNAUTHORIZED.getStatusCode(), rawresp.getStatus()); + } + + /** + * Set Up httpPrefix. + * + * @param port the port + */ + protected void setHttpPrefix(int port) { + httpPrefix = "http://" + SELF + ":" + port + "/"; + } + +} diff --git a/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/utils/ToscaUtils.java b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/utils/ToscaUtils.java new file mode 100644 index 000000000..768e18d1a --- /dev/null +++ b/participant/participant-impl/participant-impl-simulator/src/test/java/org/onap/policy/clamp/acm/participant/sim/utils/ToscaUtils.java @@ -0,0 +1,51 @@ +/*- + * ============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.participant.sim.utils; + +import lombok.AccessLevel; +import lombok.NoArgsConstructor; +import org.onap.policy.common.utils.coder.YamlJsonTranslator; +import org.onap.policy.common.utils.resources.ResourceUtils; +import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate; + +/** + * Util class for Test scope. + */ +@NoArgsConstructor(access = AccessLevel.PRIVATE) +public final class ToscaUtils { + + private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator(); + private static final String TOSCA_TEMPLATE_YAML = "clamp/acm/test/participant-http.yaml"; + + + /** + * Read a service template yaml. + * @return ToscaServiceTemplate + */ + public static ToscaServiceTemplate readAutomationCompositionFromTosca() { + return serializeAutomationCompositionYaml(); + } + + private static ToscaServiceTemplate serializeAutomationCompositionYaml() { + String automationCompositionString = ResourceUtils.getResourceAsString(ToscaUtils.TOSCA_TEMPLATE_YAML); + return yamlTranslator.fromYaml(automationCompositionString, ToscaServiceTemplate.class); + } +} |