diff --git a/src/main/java/org/opendevstack/component_provisioner/server/controllers/validators/ProvisionerActionsApiValidator.java b/src/main/java/org/opendevstack/component_provisioner/server/controllers/validators/ProvisionerActionsApiValidator.java index ae5a868..c1f6f2c 100644 --- a/src/main/java/org/opendevstack/component_provisioner/server/controllers/validators/ProvisionerActionsApiValidator.java +++ b/src/main/java/org/opendevstack/component_provisioner/server/controllers/validators/ProvisionerActionsApiValidator.java @@ -10,6 +10,7 @@ import org.opendevstack.component_provisioner.server.controllers.exceptions.ProjectComponentAlreadyProvisionedException; import org.opendevstack.component_provisioner.server.controllers.exceptions.UserNotAllowedException; import org.opendevstack.component_provisioner.server.controllers.model.ActionType; +import org.opendevstack.component_provisioner.server.facade.ProvisionActionWrapper; import org.opendevstack.component_provisioner.server.model.ProvisionAction; import org.opendevstack.component_provisioner.server.services.AuthenticationProvider; import org.opendevstack.component_provisioner.server.services.ComponentCatalogService; @@ -59,12 +60,6 @@ public void validate(ProvisionAction provisionAction) { validateUserHasPermissionsToProvision(projectKey, accessToken); } - public void validateActionHasWorkflowDefined(ProvisionAction provisionAction) { - var workflow = getWorkflow(provisionAction); - var workflowName = getWorkflowName(provisionAction); - validateWorkflowPresence(workflow, workflowName); - } - public void validateReceivesOnlyVisibleParameters(ProvisionAction provisionAction, CatalogItem catalogItem) { var catalogItemProvisionUserAction = Optional.ofNullable(catalogItem) .map(CatalogItem::getUserActions) @@ -151,9 +146,11 @@ private static void validateInputParams(String projectKey, String accessToken, S } } - private void validateWorkflowPresence(String workflow, String workflowName) { - log.debug("Validating presence of workflow or workflow_name. Workflow: {}, Workflow name: {}", workflow, workflowName); + public void validateWorkflowPresence(ProvisionAction provisionAction) { + var workflow = getWorkflow(provisionAction); + var workflowName = getWorkflowName(provisionAction); + log.debug("Validating presence of workflow or workflow_name. Workflow: {}, Workflow name: {}", workflow, workflowName); if (StringUtils.isBlank(workflow) && StringUtils.isBlank(workflowName)) { throw new InvalidRestEntityException("Either workflow or workflow_name are required."); } diff --git a/src/main/java/org/opendevstack/component_provisioner/server/facade/ProvisionResultsApiFacade.java b/src/main/java/org/opendevstack/component_provisioner/server/facade/ProvisionResultsApiFacade.java index 1591386..c48b1cb 100644 --- a/src/main/java/org/opendevstack/component_provisioner/server/facade/ProvisionResultsApiFacade.java +++ b/src/main/java/org/opendevstack/component_provisioner/server/facade/ProvisionResultsApiFacade.java @@ -1,5 +1,6 @@ package org.opendevstack.component_provisioner.server.facade; +import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.util.Strings; @@ -21,10 +22,14 @@ import org.springframework.stereotype.Service; import org.springframework.web.client.RestClientException; +import java.util.ArrayList; import java.util.Arrays; +import java.util.List; import java.util.Objects; +import java.util.stream.Collectors; @Service +@RequiredArgsConstructor @Slf4j public class ProvisionResultsApiFacade { @@ -43,22 +48,6 @@ public class ProvisionResultsApiFacade { @Value("${component-provisioner.awx.workflows.deletion-wrapper-workflow-id}") private String deletionWrapperWorkflowId; - public ProvisionResultsApiFacade(AwxService awxService, - ComponentCatalogService componentCatalogService, - EntitiesMapper entitiesMapper, - ProvisionService provisionService, - AuthenticationProvider authenticationProvider, - ProjectsInfoService projectsInfoService, - ApplicationAuthenticationProvider applicationAuthenticationProvider) { - this.awxService = awxService; - this.componentCatalogService = componentCatalogService; - this.entitiesMapper = entitiesMapper; - this.provisionService = provisionService; - this.authenticationProvider = authenticationProvider; - this.projectsInfoService = projectsInfoService; - this.applicationAuthenticationProvider = applicationAuthenticationProvider; - } - public AwxResponse requestDeletion( String projectKey, String componentId, @@ -302,6 +291,18 @@ private void addDeletionWrapperWorkflowParameters(String catalogItemId, .build() ); } + var dispatchedWorkflowParams = action.getParameters().stream().map(CreateIncidentParameter::getName).collect(Collectors.toSet()); + dispatchedWorkflowParams.add("notifications_group_id"); // This param is added later by the entitiesMapper, so we need to manually add it + + var allParams = new ArrayList<>(action.getParameters()); + var createIncidentParamDispatchedWorkflowParams = CreateIncidentParameter.builder() + .name("dispatched_workflow_params") + .value(dispatchedWorkflowParams) + .type(ParameterType.MULTIPLELIST.getValue()) + .build(); + allParams.add(createIncidentParamDispatchedWorkflowParams); + + action.setParameters(allParams); } private void addCallerParameter(CreateIncidentAction action) { diff --git a/src/main/java/org/opendevstack/component_provisioner/server/facade/ProvisionerActionsApiFacade.java b/src/main/java/org/opendevstack/component_provisioner/server/facade/ProvisionerActionsApiFacade.java index a07040a..ba940f7 100644 --- a/src/main/java/org/opendevstack/component_provisioner/server/facade/ProvisionerActionsApiFacade.java +++ b/src/main/java/org/opendevstack/component_provisioner/server/facade/ProvisionerActionsApiFacade.java @@ -15,6 +15,7 @@ import org.opendevstack.component_provisioner.server.controllers.validators.ParameterType; import org.opendevstack.component_provisioner.server.controllers.validators.ProvisionerActionsApiValidator; import org.opendevstack.component_provisioner.server.mappers.EntitiesMapper; +import org.opendevstack.component_provisioner.server.model.CreateIncidentParameter; import org.opendevstack.component_provisioner.server.model.ProvisionAction; import org.opendevstack.component_provisioner.server.model.ProvisionActionParameter; import org.opendevstack.component_provisioner.server.model.ProvisionActionResponse; @@ -24,9 +25,11 @@ import org.springframework.stereotype.Service; import org.springframework.web.client.RestClientException; +import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.Optional; +import java.util.stream.Collectors; import static org.opendevstack.component_provisioner.server.services.ProvisionerActionsParameterExtractor.getLocation; @@ -56,9 +59,10 @@ public AwxResponse triggerProvisionAction(ProvisionAction provisionAction) { provisionerActionsApiValidator.validateReceivesOnlyVisibleParameters(resolvedActionWrapper.toProvisionAction(), catalogItem); var systemParametersActionWrapper = addSystemParametersToAction(resolvedActionWrapper); var requiredCatalogItemParamsWrapper = addMandatoryCatalogItemParamsIfMissing(systemParametersActionWrapper, catalogItem); - provisionerActionsApiValidator.validateActionHasWorkflowDefined(requiredCatalogItemParamsWrapper.toProvisionAction()); - provisionerActionsApiValidator.validateMandatoryFields(requiredCatalogItemParamsWrapper.toProvisionAction(), catalogItem); - var updateProvisionActionWithoutPlaceholdersWrapper = placeholderPostProcessor.process(requiredCatalogItemParamsWrapper); + var workflowWrapperParamsActionWrapper = addProvisionWorkflowWrapper(requiredCatalogItemParamsWrapper); + provisionerActionsApiValidator.validateWorkflowPresence(workflowWrapperParamsActionWrapper.toProvisionAction()); + provisionerActionsApiValidator.validateMandatoryFields(workflowWrapperParamsActionWrapper.toProvisionAction(), catalogItem); + var updateProvisionActionWithoutPlaceholdersWrapper = placeholderPostProcessor.process(workflowWrapperParamsActionWrapper); var updatedProvisionActionWithOdsApiParametersWrapper = replaceParametersService.replaceProvisioningParametersFromOdsApi(updateProvisionActionWithoutPlaceholdersWrapper); notifyComponentCatalogProvisionStarts(updatedProvisionActionWithOdsApiParametersWrapper); @@ -113,11 +117,10 @@ public ProvisionActionWrapper addSystemParametersToAction(ProvisionActionWrapper var locationProvisionWrapper = addClusterLocationToAction(provisionActionWrapper); var callerProvisionWrapper = addCallerToAction(locationProvisionWrapper); var bearerTokenWrapper = addBearerTokenToActions(callerProvisionWrapper); - var addProvisionWorkflowWrapper = addProvisionWorkflowWrapper(bearerTokenWrapper); - log.debug("Added system parameters to provision action: '{}'", addProvisionWorkflowWrapper); + log.debug("Added system parameters to provision action: '{}'", bearerTokenWrapper); - return addProvisionWorkflowWrapper; + return bearerTokenWrapper; } private void updateAwxJobIdIntoProjectComponents(ProvisionActionWrapper provisionActionWrapper, AwxResponse awxResponse) { @@ -241,6 +244,15 @@ private ProvisionActionWrapper addProvisionWorkflowWrapper(ProvisionActionWrappe ); } + var dispatchedWorkflowParams = provisionActionWrapperWithoutWorkflowInfo.getParametersMap().values().stream().map(ProvisionActionParameter::getName).collect(Collectors.toSet()); + dispatchedWorkflowParams.add("notifications_group_id"); // This param is added later by the entitiesMapper, so we need to manually add it + var provisionParamDispatchedWorkflowParams = ProvisionActionParameter.builder() + .name("dispatched_workflow_params") + .value(dispatchedWorkflowParams) + .type(ParameterType.MULTIPLELIST.getValue()) + .build(); + parametersToAdd.add(provisionParamDispatchedWorkflowParams); + return provisionActionWrapperWithoutWorkflowInfo.cloneWithParameters(parametersToAdd); } diff --git a/src/test/java/org/opendevstack/component_provisioner/server/controllers/validators/ProvisionerActionsApiValidatorTest.java b/src/test/java/org/opendevstack/component_provisioner/server/controllers/validators/ProvisionerActionsApiValidatorTest.java index 572af6c..d5002c2 100644 --- a/src/test/java/org/opendevstack/component_provisioner/server/controllers/validators/ProvisionerActionsApiValidatorTest.java +++ b/src/test/java/org/opendevstack/component_provisioner/server/controllers/validators/ProvisionerActionsApiValidatorTest.java @@ -505,7 +505,7 @@ void validateReceivesOnlyVisibleParameters_succeedsWhenInternalParamsCombinedWit } @Test - void validateActionHasWorkflowDefined_throwsInvalidRestEntityException_whenBothWorkflowAndWorkflowNameMissing() { + void validateWorkflowPresence_throwsInvalidRestEntityException_whenBothWorkflowAndWorkflowNameMissing() { var action = ProvisionActionMother.of(List.of( ProvisionActionParameterMother.of("project_key", "pkey"), ProvisionActionParameterMother.of("component_id", "cid"), @@ -513,40 +513,41 @@ void validateActionHasWorkflowDefined_throwsInvalidRestEntityException_whenBothW ProvisionActionParameterMother.of("access_token", "accessToken") )); + // when / then assertThrows(InvalidRestEntityException.class, - () -> provisionerActionsApiValidator.validateActionHasWorkflowDefined(action)); + () -> provisionerActionsApiValidator.validateWorkflowPresence(action)); } @Test - void validateActionHasWorkflowDefined_succeeds_whenWorkflowProvidedByUser() { + void validateWorkflowPresence_succeeds_whenWorkflowProvidedByUser() { var action = ProvisionActionMother.of(List.of( ProvisionActionParameterMother.of("workflow", "wf-123") )); - assertThatNoException().isThrownBy(() -> provisionerActionsApiValidator.validateActionHasWorkflowDefined(action)); + assertThatNoException().isThrownBy(() -> provisionerActionsApiValidator.validateWorkflowPresence(action)); } @Test - void validateActionHasWorkflowDefined_succeeds_whenWorkflowNameProvidedByUser() { + void validateWorkflowPresence_succeeds_whenWorkflowNameProvidedByUser() { var action = ProvisionActionMother.of(List.of( ProvisionActionParameterMother.of("workflow_name", "wf-name") )); - assertThatNoException().isThrownBy(() -> provisionerActionsApiValidator.validateActionHasWorkflowDefined(action)); + assertThatNoException().isThrownBy(() -> provisionerActionsApiValidator.validateWorkflowPresence(action)); } @Test - void validateActionHasWorkflowDefined_succeeds_whenBothWorkflowAndWorkflowNameProvided() { + void validateWorkflowPresence_succeeds_whenBothWorkflowAndWorkflowNameProvided() { var action = ProvisionActionMother.of(List.of( ProvisionActionParameterMother.of("workflow", "wf-123"), ProvisionActionParameterMother.of("workflow_name", "wf-name") )); - assertThatNoException().isThrownBy(() -> provisionerActionsApiValidator.validateActionHasWorkflowDefined(action)); + assertThatNoException().isThrownBy(() -> provisionerActionsApiValidator.validateWorkflowPresence(action)); } @Test - void validateActionHasWorkflowDefined_succeeds_whenWorkflowComesFromHiddenCatalogItemParam() { + void validateWorkflowPresence_succeeds_whenWorkflowComesFromHiddenCatalogItemParam() { // Workflow was not provided by the user but was injected from the catalog item's // hidden (non-visible) mandatory parameter before this validation is invoked var action = ProvisionActionMother.of(List.of( @@ -556,6 +557,6 @@ void validateActionHasWorkflowDefined_succeeds_whenWorkflowComesFromHiddenCatalo ProvisionActionParameterMother.of("workflow", "wf-from-hidden-param") )); - assertThatNoException().isThrownBy(() -> provisionerActionsApiValidator.validateActionHasWorkflowDefined(action)); + assertThatNoException().isThrownBy(() -> provisionerActionsApiValidator.validateWorkflowPresence(action)); } } diff --git a/src/test/java/org/opendevstack/component_provisioner/server/facade/ProvisionResultsApiFacadeTest.java b/src/test/java/org/opendevstack/component_provisioner/server/facade/ProvisionResultsApiFacadeTest.java index 8b3988e..f4d35ab 100644 --- a/src/test/java/org/opendevstack/component_provisioner/server/facade/ProvisionResultsApiFacadeTest.java +++ b/src/test/java/org/opendevstack/component_provisioner/server/facade/ProvisionResultsApiFacadeTest.java @@ -780,4 +780,46 @@ void givenAwxTriggerFails_whenRequestDeletionIsCalled_thenReturnsErrorStatus() { assertThat(result.httpStatusCode()).isEqualTo(HttpStatus.INTERNAL_SERVER_ERROR); } + @Test + void givenWrapperWorkflow_whenAddDeletionWrapperWorkflowParametersIsCalled_thenDispatchedWorkflowParamsContainsAllParametersAndNotification() { + // given + var action = CreateIncidentActionMother.of(); + action.setParameters(new ArrayList<>()); + + when(authenticationProvider.getAccessToken()).thenReturn("token"); + + // when + ReflectionTestUtils.invokeMethod( + facade, + "addDeletionWrapperWorkflowParameters", + "catalogId", + "wfId", + "wfName", + "60", + action + ); + + // then + var dispatchedParam = action.getParameters().stream() + .filter(p -> "dispatched_workflow_params".equals(p.getName())) + .findFirst() + .orElse(null); + + assertThat(dispatchedParam).isNotNull(); + assertThat(dispatchedParam.getValue()).isInstanceOf(java.util.Set.class); + + @SuppressWarnings("unchecked") + var dispatchedSet = (java.util.Set) dispatchedParam.getValue(); + + var expectedParamNames = action.getParameters().stream() + .map(CreateIncidentParameter::getName) + .filter(name -> !"dispatched_workflow_params".equals(name)) + .toList(); + + assertThat(dispatchedSet).containsAll(expectedParamNames); + + assertThat(dispatchedSet).contains("notifications_group_id"); + } + + } diff --git a/src/test/java/org/opendevstack/component_provisioner/server/facade/ProvisionerActionsApiFacadeTest.java b/src/test/java/org/opendevstack/component_provisioner/server/facade/ProvisionerActionsApiFacadeTest.java index 19a9787..8238840 100644 --- a/src/test/java/org/opendevstack/component_provisioner/server/facade/ProvisionerActionsApiFacadeTest.java +++ b/src/test/java/org/opendevstack/component_provisioner/server/facade/ProvisionerActionsApiFacadeTest.java @@ -673,7 +673,7 @@ void addMandatoryParamsIfMissing_multipleListType_usesDefaultValues() { } @Test - void addSystemParametersToAction_whenWorkflowNameProvided_thenUsesProvisionWorkflowName() { + void addSystemParametersToAction_whenWorkflowNameProvided_thenDoesNotAddProvisionWorkflowParams() { // given var wrapper = ProvisionActionWrapperMother.of(List.of( ProvisionActionParameterMother.of("project_key", "PRJ"), @@ -689,12 +689,12 @@ void addSystemParametersToAction_whenWorkflowNameProvided_thenUsesProvisionWorkf var result = facade.addSystemParametersToAction(wrapper); // then - assertThat(result.getParameterValue("provision_workflow_name")).isEqualTo("custom-wf"); - assertThat(result.getParameterValue("provision_workflow_id")).isNull(); + assertThat(result.getParameterValue("provision_workflow_name")).isNull(); + assertThat(result.getParameterValue("workflow")).isNull(); } @Test - void addSystemParametersToAction_whenWorkflowIdProvided_thenUsesProvidedWorkflowId() { + void addSystemParametersToAction_whenWorkflowIdProvided_thenDoesNotAddProvisionWorkflowId() { // given var wrapper = ProvisionActionWrapperMother.of(List.of( ProvisionActionParameterMother.of("project_key", "PRJ"), @@ -709,11 +709,11 @@ void addSystemParametersToAction_whenWorkflowIdProvided_thenUsesProvidedWorkflow var result = facade.addSystemParametersToAction(wrapper); // then - assertThat(result.getParameterValue("provision_workflow_id")).isEqualTo("custom-id"); + assertThat(result.getParameterValue("provision_workflow_id")).isNull(); } @Test - void addSystemParametersToAction_whenTimeoutProvided_thenAddsProvisionWorkflowTimeout() { + void addSystemParametersToAction_whenTimeoutProvided_thenDoesNotAddProvisionWorkflowTimeout() { // given var wrapper = ProvisionActionWrapperMother.of(List.of( ProvisionActionParameterMother.of("project_key", "PRJ"), @@ -728,11 +728,11 @@ void addSystemParametersToAction_whenTimeoutProvided_thenAddsProvisionWorkflowTi var result = facade.addSystemParametersToAction(wrapper); // then - assertThat(result.getParameterValue("provision_workflow_timeout_seconds")).isEqualTo("120"); + assertThat(result.getParameterValue("provision_workflow_timeout_seconds")).isNull(); } @Test - void addSystemParametersToAction_removesWorkflowNameAndWorkflowTimeoutParameters() { + void addSystemParametersToAction_doesNotRemoveWorkflowParameters() { // given var wrapper = ProvisionActionWrapperMother.of(List.of( ProvisionActionParameterMother.of("project_key", "PRJ"), @@ -749,7 +749,147 @@ void addSystemParametersToAction_removesWorkflowNameAndWorkflowTimeoutParameters var result = facade.addSystemParametersToAction(wrapper); // then - assertThat(result.getParameterValue("workflow_timeout_seconds")).isNull(); - assertThat(result.getWorkflowName()).isNull(); + assertThat(result.getParameterValue("workflow")).isEqualTo("old"); + assertThat(result.getWorkflowName()).isEqualTo("old-name"); + assertThat(result.getParameterValue("workflow_timeout_seconds")).isEqualTo("120"); + } + + @Test + void addSystemParametersToAction_doesNotAddDispatchedWorkflowParams() { + // given + var wrapper = ProvisionActionWrapperMother.of(List.of( + ProvisionActionParameterMother.of("project_key", "PRJ"), + ProvisionActionParameterMother.of("catalog_item_id", "CAT"), + ProvisionActionParameterMother.of("custom_param", "value"), + ProvisionActionParameterMother.of("workflow", "wf-id"), + ProvisionActionParameterMother.of("workflow_name", "wf-name"), + ProvisionActionParameterMother.of("workflow_timeout_seconds", "120") + )); + + setupSystemParameterMocks(); + ReflectionTestUtils.setField(facade, "provisionWrapperWorkflowId", "WRAPPER_WF"); + + // when + var result = facade.addSystemParametersToAction(wrapper); + + // then + assertThat(result.getParameterValue("dispatched_workflow_params")).isNull(); } + + @Test + void triggerProvisionAction_addsProvisionWorkflowParameters() { + // given + var action = ProvisionActionMother.of(List.of( + ProvisionActionParameterMother.of("project_key", "PRJ"), + ProvisionActionParameterMother.of("catalog_item_id", "CAT"), + ProvisionActionParameterMother.of("workflow_name", "custom-wf") + )); + + setupSystemParameterMocks(); + + var awxWorkflowJobLaunch = AwxWorkflowJobLaunchMother.of(); + var awxWorkflowJob = AwxWorkflowJobMother.of(); + + var provisionActionResponse = ProvisionActionResponseMother.of(); + provisionActionResponse.setId(123); + + when(placeholderPostProcessor.process(any())) + .thenAnswer(inv -> inv.getArgument(0)); + + ArgumentCaptor captor = ArgumentCaptor.forClass(ProvisionActionWrapper.class); + + when(replaceParametersService.replaceProvisioningParametersFromOdsApi(captor.capture())) + .thenAnswer(inv -> inv.getArgument(0)); + + when(entitiesMapper.asAwxWorkflowJobLaunch((ProvisionAction) any())) + .thenReturn(awxWorkflowJobLaunch); + + when(entitiesMapper.asProvisionActionResponse(awxWorkflowJob)) + .thenReturn(provisionActionResponse); + + when(awxService.triggerWorkflowJob(any(), any())) + .thenReturn(Pair.of(HttpStatus.OK, Optional.of(awxWorkflowJob))); + + // when + facade.triggerProvisionAction(action); + + // then + var wrapper = captor.getValue(); + + var provisionWorkflowName = wrapper.getParametersMap().values().stream() + .filter(p -> "provision_workflow_name".equals(p.getName())) + .findFirst() + .orElseThrow(); + + assertThat(provisionWorkflowName.getValue()).isEqualTo("custom-wf"); + + assertThat(wrapper.getParametersMap()).containsKey("workflow"); + } + + @Test + void triggerProvisionAction_callsValidateWorkflowPresence() { + // given + var action = ProvisionActionMother.of(List.of( + ProvisionActionParameterMother.of("project_key", "PRJ"), + ProvisionActionParameterMother.of("catalog_item_id", "CAT") + )); + + setupSystemParameterMocks(); + + var provisionActionResponse = ProvisionActionResponseMother.of(); + provisionActionResponse.setId(123); + + when(placeholderPostProcessor.process(any())) + .thenAnswer(inv -> inv.getArgument(0)); + when(replaceParametersService.replaceProvisioningParametersFromOdsApi(any())) + .thenAnswer(inv -> inv.getArgument(0)); + when(entitiesMapper.asAwxWorkflowJobLaunch((ProvisionAction) any())) + .thenReturn(AwxWorkflowJobLaunchMother.of()); + when(entitiesMapper.asProvisionActionResponse(any())) + .thenReturn(provisionActionResponse); + when(awxService.triggerWorkflowJob(any(), any())) + .thenReturn(Pair.of(HttpStatus.OK, Optional.of(AwxWorkflowJobMother.of()))); + + // when + facade.triggerProvisionAction(action); + + // then + verify(provisionerActionsApiValidator) + .validateWorkflowPresence(any()); + } + + @Test + void triggerProvisionAction_appliesWorkflowWrapper_beforePlaceholderProcessing() { + // given + var action = ProvisionActionMother.of(List.of( + ProvisionActionParameterMother.of("project_key", "PRJ"), + ProvisionActionParameterMother.of("catalog_item_id", "CAT") + )); + + setupSystemParameterMocks(); + + var provisionActionResponse = ProvisionActionResponseMother.of(); + provisionActionResponse.setId(123); + + when(placeholderPostProcessor.process(any())) + .thenAnswer(inv -> inv.getArgument(0)); + when(replaceParametersService.replaceProvisioningParametersFromOdsApi(any())) + .thenAnswer(inv -> inv.getArgument(0)); + when(entitiesMapper.asAwxWorkflowJobLaunch((ProvisionAction) any())) + .thenReturn(AwxWorkflowJobLaunchMother.of()); + when(entitiesMapper.asProvisionActionResponse(any())) + .thenReturn(provisionActionResponse); + when(awxService.triggerWorkflowJob(any(), any())) + .thenReturn(Pair.of(HttpStatus.OK, Optional.of(AwxWorkflowJobMother.of()))); + + // when + facade.triggerProvisionAction(action); + + // then + var order = inOrder(provisionerActionsApiValidator, placeholderPostProcessor); + + order.verify(provisionerActionsApiValidator).validateWorkflowPresence(any()); + order.verify(placeholderPostProcessor).process(any()); + } + }