package com.sequenceiq.cloudbreak.core.flow2.stack.repair; import java.util.Map; import java.util.Optional; import javax.inject.Inject; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.statemachine.StateContext; import org.springframework.statemachine.action.Action; import com.sequenceiq.cloudbreak.api.model.Status; import com.sequenceiq.cloudbreak.cloud.event.Payload; import com.sequenceiq.cloudbreak.cloud.event.Selectable; import com.sequenceiq.cloudbreak.core.flow2.AbstractAction; import com.sequenceiq.cloudbreak.core.flow2.stack.FlowMessageService; import com.sequenceiq.cloudbreak.core.flow2.stack.Msg; import com.sequenceiq.cloudbreak.domain.Stack; import com.sequenceiq.cloudbreak.reactor.api.event.StackEvent; import com.sequenceiq.cloudbreak.reactor.api.event.StackFailureEvent; import com.sequenceiq.cloudbreak.reactor.api.event.resource.UnhealthyInstancesDetectionRequest; import com.sequenceiq.cloudbreak.reactor.api.event.resource.UnhealthyInstancesDetectionResult; import com.sequenceiq.cloudbreak.service.stack.StackService; import com.sequenceiq.cloudbreak.service.stack.repair.StackRepairService; @Configuration public class ManualStackRepairTriggerActions { @Inject private StackRepairService stackRepairService; @Inject private FlowMessageService flowMessageService; @Bean(name = "UNHEALTHY_INSTANCES_DETECTION_STATE") public Action detectUnhealthyInstancesAction() { return new AbstractStackRepairTriggerAction<StackEvent>(StackEvent.class) { @Override protected void doExecute(StackRepairTriggerContext context, StackEvent payload, Map<Object, Object> variables) throws Exception { flowMessageService.fireEventAndLog(payload.getStackId(), Msg.STACK_REPAIR_DETECTION_STARTED, Status.UPDATE_IN_PROGRESS.name()); sendEvent(context); } @Override protected Selectable createRequest(StackRepairTriggerContext context) { return new UnhealthyInstancesDetectionRequest(context.getStack().getId()); } }; } @Bean(name = "NOTIFY_STACK_REPAIR_SERVICE_STATE") public Action notifyStackRepairServiceAction() { return new AbstractStackRepairTriggerAction<UnhealthyInstancesDetectionResult>(UnhealthyInstancesDetectionResult.class) { @Override protected void doExecute(StackRepairTriggerContext context, UnhealthyInstancesDetectionResult payload, Map<Object, Object> variables) throws Exception { stackRepairService.add(context.getStack(), payload.getUnhealthyInstanceIds()); sendEvent(context); } @Override protected Selectable createRequest(StackRepairTriggerContext context) { return new StackEvent(ManualStackRepairTriggerEvent.REPAIR_SERVICE_NOTIFIED_EVENT.event(), context.getStack().getId()); } }; } @Bean(name = "MANUAL_STACK_REPAIR_TRIGGER_FAILED_STATE") public Action handleErrorAction() { return new AbstractStackRepairTriggerAction<UnhealthyInstancesDetectionResult>(UnhealthyInstancesDetectionResult.class) { @Override protected void doExecute(StackRepairTriggerContext context, UnhealthyInstancesDetectionResult payload, Map<Object, Object> variables) throws Exception { flowMessageService.fireEventAndLog(payload.getStackId(), Msg.STACK_REPAIR_FAILED, Status.AVAILABLE.name(), payload.getStatusReason()); sendEvent(context); } @Override protected Selectable createRequest(StackRepairTriggerContext context) { return new StackEvent(ManualStackRepairTriggerEvent.MANUAL_STACK_REPAIR_TRIGGER_FAILURE_HANDLED_EVENT.event(), context.getStack().getId()); } }; } private abstract class AbstractStackRepairTriggerAction<P extends Payload> extends AbstractAction<ManualStackRepairTriggerState, ManualStackRepairTriggerEvent, StackRepairTriggerContext, P> { @Inject private StackService stackService; protected AbstractStackRepairTriggerAction(Class<P> payloadClass) { super(payloadClass); } @Override protected StackRepairTriggerContext createFlowContext( String flowId, StateContext<ManualStackRepairTriggerState, ManualStackRepairTriggerEvent> stateContext, P payload) { Long stackId = payload.getStackId(); Stack stack = stackService.getById(stackId); return new StackRepairTriggerContext(flowId, stack); } @Override protected Object getFailurePayload(P payload, Optional<StackRepairTriggerContext> flowContext, Exception ex) { return new StackFailureEvent(payload.getStackId(), ex); } } }