Skip to content

Commit

Permalink
feat(cloudfoundry): Uses last operation state & description (#4138)
Browse files Browse the repository at this point in the history
* feat(cloudfoundry): Uses last operation state & description to surface that something went wrong.

* feat(cloudfoundry): Adds null check.

* feat(cloudfoundry): Adds default message.

Co-authored-by: Zach Smith <33258732+zachsmith1@users.noreply.github.com>
  • Loading branch information
rvazquezglez and zachsmith1 committed Jul 6, 2021
1 parent 7a88c0f commit 7e0b4c9
Show file tree
Hide file tree
Showing 3 changed files with 88 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,14 @@

package com.netflix.spinnaker.orca.clouddriver.tasks.providers.cf;

import com.netflix.spinnaker.orca.api.pipeline.TaskResult;
import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus;
import com.netflix.spinnaker.orca.api.pipeline.models.StageExecution;
import com.netflix.spinnaker.orca.clouddriver.OortService;
import com.netflix.spinnaker.orca.clouddriver.tasks.servicebroker.AbstractWaitForServiceTask;
import java.util.Map;
import java.util.Optional;
import javax.annotation.Nonnull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

Expand All @@ -31,6 +34,41 @@ public CloudFoundryWaitForDeployServiceTask(OortService oortService) {
super(oortService);
}

@Nonnull
@Override
public TaskResult execute(@Nonnull StageExecution stage) {
String cloudProvider = getCloudProvider(stage);
String account = stage.mapTo("/service.account", String.class);
String region = stage.mapTo("/service.region", String.class);
String serviceInstanceName = stage.mapTo("/service.instance.name", String.class);

Map<String, Object> serviceInstance =
oortService.getServiceInstance(account, cloudProvider, region, serviceInstanceName);

ExecutionStatus status = oortStatusToTaskStatus(serviceInstance);

TaskResult.TaskResultBuilder taskResultBuilder = TaskResult.builder(status);
Optional.ofNullable(serviceInstance)
.ifPresent(
(si) -> {
String lastOperationDescription =
Optional.ofNullable(serviceInstance.get("lastOperationDescription"))
.orElse("Failed to get last operation description")
.toString();
taskResultBuilder
.output(
"lastOperationStatus",
Optional.ofNullable(serviceInstance.get("status")).orElse("").toString())
.output("lastOperationDescription", lastOperationDescription);
if (status == ExecutionStatus.TERMINAL) {
taskResultBuilder.output("failureMessage", lastOperationDescription);
}
});

return taskResultBuilder.build();
}

@Override
protected ExecutionStatus oortStatusToTaskStatus(Map m) {
return Optional.ofNullable(m)
.map(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,8 @@
import javax.annotation.Nullable;

class AbstractCloudFoundryWaitForServiceOperationTaskTest<T extends AbstractWaitForServiceTask> {
private final String operationType;
private final Function<OortService, T> subjectConstructor;
protected final String operationType;
protected final Function<OortService, T> subjectConstructor;

AbstractCloudFoundryWaitForServiceOperationTaskTest(
String operationType, Function<OortService, T> subjectConstructor) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,20 @@

package com.netflix.spinnaker.orca.clouddriver.tasks.providers.cf;

import static com.netflix.spinnaker.orca.api.pipeline.models.ExecutionType.PIPELINE;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.ArgumentMatchers.matches;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

import com.netflix.spinnaker.orca.api.pipeline.TaskResult;
import com.netflix.spinnaker.orca.api.pipeline.models.ExecutionStatus;
import com.netflix.spinnaker.orca.clouddriver.OortService;
import com.netflix.spinnaker.orca.pipeline.model.PipelineExecutionImpl;
import com.netflix.spinnaker.orca.pipeline.model.StageExecutionImpl;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import org.junit.jupiter.api.Test;

class CloudFoundryWaitForDeployServiceTaskTest
Expand All @@ -44,6 +56,42 @@ void isRunningWhenOortResultIsInProgress() {
ExecutionStatus.RUNNING, Collections.singletonMap("status", "IN_PROGRESS"));
}

@Test
void addsLastOperationStatusAndDescriptinoWhenOortResultIsFailed() {
OortService oortService = mock(OortService.class);
String credentials = "my-account";
String cloudProvider = "cloud";
String region = "org > space";
String serviceInstanceName = "service-instance-name";
when(oortService.getServiceInstance(
matches(credentials),
matches(cloudProvider),
matches(region),
matches(serviceInstanceName)))
.thenReturn(
Map.of(
"status", "FAILED",
"lastOperationDescription", "Custom description"));

CloudFoundryWaitForDeployServiceTask task = subjectConstructor.apply(oortService);

Map<String, Object> context = new HashMap<>();
context.put("cloudProvider", cloudProvider);
context.put("service.account", credentials);
context.put("service.region", region);
context.put("service.instance.name", serviceInstanceName);

TaskResult result =
task.execute(
new StageExecutionImpl(
new PipelineExecutionImpl(PIPELINE, "orca"), operationType, context));

assertThat(result.getStatus().toString()).isEqualTo(ExecutionStatus.TERMINAL.toString());
assertThat(result.getOutputs().get("lastOperationStatus")).isEqualTo("FAILED");
assertThat(result.getOutputs().get("lastOperationDescription")).isEqualTo("Custom description");
assertThat(result.getOutputs().get("failureMessage")).isEqualTo("Custom description");
}

@Test
void isRunningWhenOortResultsAreEmpty() {
testOortServiceStatus(ExecutionStatus.RUNNING, Collections.emptyMap());
Expand Down

0 comments on commit 7e0b4c9

Please sign in to comment.