From 3ed75c954dcaaa8953846a129a48938e2498569a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Risue=C3=B1o?= Date: Fri, 22 May 2026 09:33:16 +0200 Subject: [PATCH 1/6] Add parameter dispatching when calling the inner wokrkflow --- .../facade/ProvisionResultsApiFacade.java | 32 +++++++++---------- .../facade/ProvisionerActionsApiFacade.java | 12 +++++++ 2 files changed, 28 insertions(+), 16 deletions(-) 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..22645a6 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,17 @@ 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()); + allParams.add(CreateIncidentParameter.builder() + .name("dispatched_workflow_params") + .value(dispatchedWorkflowParams) + .type(ParameterType.MULTIPLELIST.getValue()) + .build() + ); + 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 31a474e..5235fc0 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; @@ -240,6 +243,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 + parametersToAdd.add( + ProvisionActionParameter.builder() + .name("dispatched_workflow_params") + .value(dispatchedWorkflowParams) + .type(ParameterType.MULTIPLELIST.getValue()) + .build() + ); return provisionActionWrapperWithoutWorkflowInfo.cloneWithParameters(parametersToAdd); } From 5e7331059a3550b6112336969106015c736e866a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Risue=C3=B1o?= Date: Fri, 22 May 2026 10:50:21 +0200 Subject: [PATCH 2/6] Add tests --- .../facade/ProvisionResultsApiFacadeTest.java | 42 +++++++++++++++++++ .../ProvisionerActionsApiFacadeTest.java | 39 +++++++++++++++++ 2 files changed, 81 insertions(+) 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..09e48a1 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 @@ -752,4 +752,43 @@ void addSystemParametersToAction_removesWorkflowNameAndWorkflowTimeoutParameters assertThat(result.getParameterValue("workflow_timeout_seconds")).isNull(); assertThat(result.getWorkflowName()).isNull(); } + + @Test + void addSystemParametersToAction_addsDispatchedWorkflowParamsContainingAllParametersAndNotificationsGroup() { + // 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 + var dispatchedValue = result.getParameterValue("dispatched_workflow_params"); + + assertThat(dispatchedValue).isNotNull(); + + var expectedParamNames = List.of( + "project_key", + "catalog_item_id", + "custom_param", + "cluster_location", + "caller", + "access_token" + ); + + expectedParamNames.forEach(name -> + assertThat(dispatchedValue).contains(name) + ); + + assertThat(dispatchedValue).contains("notifications_group_id"); + } } From b8387ea649f4e6088eeab627e5e72e88a3d5b091 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Risue=C3=B1o?= Date: Fri, 22 May 2026 10:53:12 +0200 Subject: [PATCH 3/6] Improve debugability of the dispatchedWorkflowParams injection --- .../server/facade/ProvisionResultsApiFacade.java | 7 ++++--- .../server/facade/ProvisionerActionsApiFacade.java | 14 +++++++------- 2 files changed, 11 insertions(+), 10 deletions(-) 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 22645a6..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 @@ -295,12 +295,13 @@ private void addDeletionWrapperWorkflowParameters(String catalogItemId, 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()); - allParams.add(CreateIncidentParameter.builder() + var createIncidentParamDispatchedWorkflowParams = CreateIncidentParameter.builder() .name("dispatched_workflow_params") .value(dispatchedWorkflowParams) .type(ParameterType.MULTIPLELIST.getValue()) - .build() - ); + .build(); + allParams.add(createIncidentParamDispatchedWorkflowParams); + action.setParameters(allParams); } 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 5235fc0..790fed0 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 @@ -245,13 +245,13 @@ 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 - parametersToAdd.add( - ProvisionActionParameter.builder() - .name("dispatched_workflow_params") - .value(dispatchedWorkflowParams) - .type(ParameterType.MULTIPLELIST.getValue()) - .build() - ); + var provisionParamDispatchedWorkflowParams = ProvisionActionParameter.builder() + .name("dispatched_workflow_params") + .value(dispatchedWorkflowParams) + .type(ParameterType.MULTIPLELIST.getValue()) + .build(); + parametersToAdd.add(provisionParamDispatchedWorkflowParams); + return provisionActionWrapperWithoutWorkflowInfo.cloneWithParameters(parametersToAdd); } From ed187fac4f5847493292357588a5a59e2adfe1bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Risue=C3=B1o?= Date: Fri, 22 May 2026 12:58:14 +0200 Subject: [PATCH 4/6] Fix workflow and workflow_name validation occuring too early --- .../validators/ProvisionerActionsApiValidator.java | 11 +++++------ .../server/facade/ProvisionerActionsApiFacade.java | 11 ++++++----- 2 files changed, 11 insertions(+), 11 deletions(-) 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 d0a9a3c..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; @@ -51,15 +52,11 @@ public void validate(ProvisionAction provisionAction) { var projectKey = getProjectKey(provisionAction); var componentId = getComponentId(provisionAction); var accessToken = authenticationProvider.getAccessToken(); - var workflow = getWorkflow(provisionAction); - var workflowName = getWorkflowName(provisionAction); validateInputParams(projectKey, accessToken, componentId); validateComponentIsNotProvisioned(projectKey, componentId); - validateWorkflowPresence(workflow, workflowName); - validateUserHasPermissionsToProvision(projectKey, accessToken); } @@ -149,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/ProvisionerActionsApiFacade.java b/src/main/java/org/opendevstack/component_provisioner/server/facade/ProvisionerActionsApiFacade.java index 790fed0..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 @@ -59,8 +59,10 @@ public AwxResponse triggerProvisionAction(ProvisionAction provisionAction) { provisionerActionsApiValidator.validateReceivesOnlyVisibleParameters(resolvedActionWrapper.toProvisionAction(), catalogItem); var systemParametersActionWrapper = addSystemParametersToAction(resolvedActionWrapper); var requiredCatalogItemParamsWrapper = addMandatoryCatalogItemParamsIfMissing(systemParametersActionWrapper, catalogItem); - 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); @@ -115,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) { From 8920ce40c8831d7271ee077c90331ea80b62a545 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Risue=C3=B1o?= Date: Fri, 22 May 2026 13:18:59 +0200 Subject: [PATCH 5/6] Add tests --- .../ProvisionerActionsApiValidatorTest.java | 5 +- .../ProvisionerActionsApiFacadeTest.java | 151 +++++++++++++++--- 2 files changed, 127 insertions(+), 29 deletions(-) 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 a8f3c73..2eb666d 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 @@ -514,12 +514,9 @@ void validate_throwsInvalidRestEntityException_whenBothWorkflowAndWorkflowNameMi ProvisionActionParameterMother.of("access_token", "accessToken") )); - when(authenticationProvider.getAccessToken()).thenReturn("accessToken"); - when(componentCatalogService.getProjectComponents(any(), any())).thenReturn(List.of()); - // when / then assertThrows(InvalidRestEntityException.class, - () -> provisionerActionsApiValidator.validate(action)); + () -> provisionerActionsApiValidator.validateWorkflowPresence(action)); } @Test 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 09e48a1..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,12 +749,13 @@ 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_addsDispatchedWorkflowParamsContainingAllParametersAndNotificationsGroup() { + void addSystemParametersToAction_doesNotAddDispatchedWorkflowParams() { // given var wrapper = ProvisionActionWrapperMother.of(List.of( ProvisionActionParameterMother.of("project_key", "PRJ"), @@ -772,23 +773,123 @@ void addSystemParametersToAction_addsDispatchedWorkflowParamsContainingAllParame var result = facade.addSystemParametersToAction(wrapper); // then - var dispatchedValue = result.getParameterValue("dispatched_workflow_params"); + 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(); - assertThat(dispatchedValue).isNotNull(); + 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()))); - var expectedParamNames = List.of( - "project_key", - "catalog_item_id", - "custom_param", - "cluster_location", - "caller", - "access_token" - ); + // when + facade.triggerProvisionAction(action); - expectedParamNames.forEach(name -> - assertThat(dispatchedValue).contains(name) - ); + // then + var order = inOrder(provisionerActionsApiValidator, placeholderPostProcessor); - assertThat(dispatchedValue).contains("notifications_group_id"); + order.verify(provisionerActionsApiValidator).validateWorkflowPresence(any()); + order.verify(placeholderPostProcessor).process(any()); } + } From 9f42d33f049f8e35f491d2ba46bcf769098a497a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Iv=C3=A1n=20Risue=C3=B1o?= Date: Fri, 22 May 2026 13:27:57 +0200 Subject: [PATCH 6/6] Fix method naming and tests --- .../ProvisionerActionsApiValidator.java | 6 ------ .../ProvisionerActionsApiValidatorTest.java | 18 +++++++++--------- 2 files changed, 9 insertions(+), 15 deletions(-) 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 0366166..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 @@ -60,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) 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 3a7f5a2..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"), @@ -519,35 +519,35 @@ void validateActionHasWorkflowDefined_throwsInvalidRestEntityException_whenBothW } @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( @@ -557,6 +557,6 @@ void validateActionHasWorkflowDefined_succeeds_whenWorkflowComesFromHiddenCatalo ProvisionActionParameterMother.of("workflow", "wf-from-hidden-param") )); - assertThatNoException().isThrownBy(() -> provisionerActionsApiValidator.validateActionHasWorkflowDefined(action)); + assertThatNoException().isThrownBy(() -> provisionerActionsApiValidator.validateWorkflowPresence(action)); } }