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 f4f8c44..a69f667 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 @@ -18,6 +18,8 @@ import org.springframework.stereotype.Service; import java.util.List; +import java.util.Objects; +import java.util.Optional; @Service @Slf4j @@ -97,6 +99,7 @@ private String getParameterString(ProvisionAction provisionAction, String parame return provisionAction.getParameters().stream() .filter(parameter -> parameterName.equals(parameter.getName())) .map(ProvisionActionParameter::getValue) + .filter(Objects::nonNull) .map(Object::toString) .findAny() .orElse(Strings.EMPTY); @@ -156,8 +159,25 @@ private AwxWorkflowJobLaunch buildAwxWorkflowJobLaunch(ProvisionAction provision .value(provisionAction.getId()) .build(); - provisionAction.addParametersItem(parameterItem); + var updatedProvisionAction = addParametersItem(provisionAction, parameterItem); - return entitiesMapper.asAwxWorkflowJobLaunch(provisionAction); + return entitiesMapper.asAwxWorkflowJobLaunch(updatedProvisionAction); + } + + // In order to be safe, we create a new ProvisionAction instance with the additional parameter instead of modifying the existing one (which might be immutable or shared). + private ProvisionAction addParametersItem(ProvisionAction provisionAction, ProvisionActionParameter parameterItem) { + return Optional.ofNullable(parameterItem) + .map(item -> { + var newParameters = provisionAction.getParameters() == null + ? List.of(item) + : java.util.stream.Stream.concat(provisionAction.getParameters().stream(), java.util.stream.Stream.of(item)) + .toList(); + + return provisionAction.toBuilder() + .id(provisionAction.getId()) + .parameters(newParameters) + .build(); + }) + .orElse(provisionAction); } } 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 78e317c..d0d41c1 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 @@ -10,6 +10,7 @@ import org.opendevstack.component_catalog.client.projects_info_service.v1_0_0.model.ProjectInfo; import org.opendevstack.component_provisioner.server.controllers.exceptions.ProjectConfigurationException; import org.opendevstack.component_provisioner.server.mappers.EntitiesMapper; +import org.opendevstack.component_provisioner.server.model.ProvisionAction; import org.opendevstack.component_provisioner.server.model.ProvisionActionMother; import org.opendevstack.component_provisioner.server.model.ProvisionActionParameter; import org.opendevstack.component_provisioner.server.model.ProvisionActionParameterMother; @@ -62,7 +63,8 @@ void requestProvisionToAwx_mapsResponseCorrectly() { var job = new AwxWorkflowJob(); var response = new ProvisionActionResponse(); - when(entitiesMapper.asAwxWorkflowJobLaunch(action)).thenReturn(launch); + ArgumentCaptor actionCaptor = ArgumentCaptor.forClass(ProvisionAction.class); + when(entitiesMapper.asAwxWorkflowJobLaunch(actionCaptor.capture())).thenReturn(launch); when(awxService.triggerWorkflowJob(action.getId(), launch)) .thenReturn(Pair.of(HttpStatus.OK, Optional.of(job))); when(entitiesMapper.asProvisionActionResponse(job)).thenReturn(response); @@ -73,6 +75,10 @@ void requestProvisionToAwx_mapsResponseCorrectly() { // then assertEquals(HttpStatus.OK, result.httpStatusCode()); assertEquals(response, result.awxResponseBody()); + + var capturedAction = actionCaptor.getValue(); + assertThat(capturedAction.getParameters()) + .anyMatch(p -> "action_id".equals(p.getName()) && action.getId().equals(p.getValue())); } @Test @@ -192,4 +198,31 @@ void addSystemParametersToAction_usesFirstCluster_whenMultipleClustersAreReturne assertThat(clusterLocation).isEqualTo("cluster-primary"); } + @Test + void requestProvisionToAwx_addsActionIdParameter_whenParametersIsNull() { + // given + var action = ProvisionActionMother.of(null); + + var launch = new AwxWorkflowJobLaunch(); + var job = new AwxWorkflowJob(); + var response = new ProvisionActionResponse(); + + ArgumentCaptor actionCaptor = ArgumentCaptor.forClass(ProvisionAction.class); + when(entitiesMapper.asAwxWorkflowJobLaunch(actionCaptor.capture())).thenReturn(launch); + when(awxService.triggerWorkflowJob(action.getId(), launch)) + .thenReturn(Pair.of(HttpStatus.OK, Optional.of(job))); + when(entitiesMapper.asProvisionActionResponse(job)).thenReturn(response); + + // when + var result = facade.requestProvisionToAwx(action); + + // then + assertEquals(HttpStatus.OK, result.httpStatusCode()); + assertEquals(response, result.awxResponseBody()); + + var capturedAction = actionCaptor.getValue(); + assertThat(capturedAction.getParameters()) + .hasSize(1) + .anyMatch(p -> "action_id".equals(p.getName()) && action.getId().equals(p.getValue())); + } }