@Override
 public void updateAllowedSubnets(Stack stack, String gateWayUserData, String coreUserData) {
   LOGGER.debug("Assembling update subnet event for: {}", stack);
   CloudContext cloudContext = new CloudContext(stack);
   CloudCredential cloudCredential = credentialConverter.convert(stack.getCredential());
   CloudStack cloudStack = cloudStackConverter.convert(stack, coreUserData, gateWayUserData);
   List<CloudResource> resources = cloudResourceConverter.convert(stack.getResources());
   UpdateStackRequest<UpdateStackResult> updateRequest =
       new UpdateStackRequest<>(cloudContext, cloudCredential, cloudStack, resources);
   eventBus.notify(updateRequest.selector(), Event.wrap(updateRequest));
   try {
     UpdateStackResult res = updateRequest.await();
     LOGGER.info("Update stack result: {}", res);
     if (res.isFailed()) {
       if (res.getException() != null) {
         LOGGER.error("Failed to update the stack", res.getException());
         throw new OperationException(res.getException());
       }
       throw new OperationException(
           format(
               "Failed to update the stack: %s due to: %s", cloudContext, res.getStatusReason()));
     }
   } catch (InterruptedException e) {
     LOGGER.error("Error while updating the stack: " + cloudContext, e);
     throw new OperationException(e);
   }
 }
 @Override
 public Set<String> getSSHFingerprints(Stack stack, String gateway) {
   Set<String> result = new HashSet<>();
   LOGGER.debug("Get SSH fingerprints of gateway instance for stack: {}", stack);
   CloudContext cloudContext = new CloudContext(stack);
   CloudCredential cloudCredential = credentialConverter.convert(stack.getCredential());
   InstanceMetaData gatewayMetaData =
       stack.getGatewayInstanceGroup().getInstanceMetaData().iterator().next();
   CloudInstance gatewayInstance = metadataConverter.convert(gatewayMetaData);
   GetSSHFingerprintsRequest<GetSSHFingerprintsResult> sSHFingerprintReq =
       new GetSSHFingerprintsRequest<>(cloudContext, cloudCredential, gatewayInstance);
   LOGGER.info("Triggering GetSSHFingerprintsRequest stack event: {}", sSHFingerprintReq);
   eventBus.notify(sSHFingerprintReq.selector(), Event.wrap(sSHFingerprintReq));
   try {
     GetSSHFingerprintsResult res = sSHFingerprintReq.await();
     LOGGER.info("Get SSH fingerprints of gateway instance for stack result: {}", res);
     if (res.getStatus().equals(EventStatus.FAILED)) {
       LOGGER.error("Failed to get SSH fingerprint", res.getErrorDetails());
       throw new OperationException(res.getErrorDetails());
     }
     result.addAll(res.getSshFingerprints());
   } catch (InterruptedException e) {
     LOGGER.error(
         format("Failed to get SSH fingerprints of gateway instance stack: %s", cloudContext), e);
     throw new OperationException(e);
   }
   return result;
 }
 @Override
 public void stopAll(Stack stack) {
   LOGGER.info("Assembling stop request for stack: {}", stack);
   CloudContext cloudContext = new CloudContext(stack);
   CloudCredential cloudCredential = credentialConverter.convert(stack.getCredential());
   List<CloudInstance> instances = metadataConverter.convert(stack.getInstanceMetaDataAsList());
   List<CloudResource> resources = cloudResourceConverter.convert(stack.getResources());
   StopInstancesRequest<StopInstancesResult> stopRequest =
       new StopInstancesRequest<>(cloudContext, cloudCredential, resources, instances);
   LOGGER.info("Triggering event: {}", stopRequest);
   eventBus.notify(stopRequest.selector(), Event.wrap(stopRequest));
   try {
     StopInstancesResult res = stopRequest.await();
     LOGGER.info("Result: {}", res);
     if (res.isFailed()) {
       Exception exception = res.getException();
       LOGGER.error("Failed to stop the stack", exception);
       throw new OperationException(exception);
     } else {
       for (CloudVmInstanceStatus instanceStatus : res.getResults().getResults()) {
         if (instanceStatus.getStatus().equals(InstanceStatus.FAILED)) {
           throw new OperationException(
               "Failed to stop the following instance: " + instanceStatus.getCloudInstance());
         }
       }
     }
   } catch (InterruptedException e) {
     LOGGER.error("Error while stopping the stack", e);
     throw new OperationException(e);
   }
 }
 @Override
 public void deleteStack(Stack stack, Credential credential) {
   LOGGER.debug("Assembling terminate stack event for stack: {}", stack);
   CloudContext cloudContext = new CloudContext(stack);
   CloudCredential cloudCredential = credentialConverter.convert(stack.getCredential());
   List<CloudResource> resources = cloudResourceConverter.convert(stack.getResources());
   CloudStack cloudStack = cloudStackConverter.convert(stack, "", "");
   TerminateStackRequest<TerminateStackResult> terminateRequest =
       new TerminateStackRequest<>(cloudContext, cloudStack, cloudCredential, resources);
   LOGGER.info("Triggering terminate stack event: {}", terminateRequest);
   eventBus.notify(terminateRequest.selector(), Event.wrap(terminateRequest));
   try {
     TerminateStackResult res = terminateRequest.await();
     LOGGER.info("Terminate stack result: {}", res);
     if (res.getStatus().equals(EventStatus.FAILED)) {
       if (res.getErrorDetails() != null) {
         LOGGER.error("Failed to terminate the stack", res.getErrorDetails());
         throw new OperationException(res.getErrorDetails());
       }
       throw new OperationException(
           format(
               "Failed to terminate the stack: %s due to %s",
               cloudContext, res.getStatusReason()));
     }
   } catch (InterruptedException e) {
     LOGGER.error("Error while terminating the stack", e);
     throw new OperationException(e);
   }
 }
 @Override
 public Set<Resource> buildStack(
     Stack stack,
     String gateWayUserData,
     String coreUserData,
     Map<String, Object> setupProperties) {
   LOGGER.info("Assembling launch request for stack: {}", stack);
   CloudContext cloudContext = new CloudContext(stack);
   CloudCredential cloudCredential = credentialConverter.convert(stack.getCredential());
   CloudStack cloudStack = cloudStackConverter.convert(stack, coreUserData, gateWayUserData);
   instanceMetadataService.saveInstanceRequests(stack, cloudStack.getGroups());
   LaunchStackRequest launchRequest =
       new LaunchStackRequest(cloudContext, cloudCredential, cloudStack);
   LOGGER.info("Triggering event: {}", launchRequest);
   eventBus.notify(launchRequest.selector(), Event.wrap(launchRequest));
   try {
     LaunchStackResult res = launchRequest.await();
     LOGGER.info("Result: {}", res);
     validateResourceResults(cloudContext, res);
     List<CloudResourceStatus> results = res.getResults();
     updateNodeCount(stack.getId(), cloudStack.getGroups(), results, true);
     return transformResults(results, stack);
   } catch (InterruptedException e) {
     LOGGER.error("Error while launching stack", e);
     throw new OperationException(
         "Unexpected exception occurred during build stack: " + e.getMessage());
   }
 }
 @Override
 public void triggerStackDownscale(Object object) {
   UpdateInstancesRequest updateRequest = (UpdateInstancesRequest) object;
   StackScalingContext context = new StackScalingContext(updateRequest);
   reactor.notify(
       FlowPhases.STACK_DOWNSCALE.name(),
       eventFactory.createEvent(context, FlowPhases.STACK_DOWNSCALE.name()));
 }
 @Override
 public void triggerStackRemoveInstance(Object object) {
   RemoveInstanceRequest removeInstanceRequest = (RemoveInstanceRequest) object;
   StackInstanceUpdateContext context = new StackInstanceUpdateContext(removeInstanceRequest);
   reactor.notify(
       FlowPhases.REMOVE_INSTANCE.name(),
       eventFactory.createEvent(context, FlowPhases.REMOVE_INSTANCE.name()));
 }
 @Override
 public void triggerClusterDownscale(Object object) {
   UpdateAmbariHostsRequest request = (UpdateAmbariHostsRequest) object;
   ClusterScalingContext context = new ClusterScalingContext(request);
   reactor.notify(
       FlowPhases.CLUSTER_DOWNSCALE.name(),
       eventFactory.createEvent(context, FlowPhases.CLUSTER_DOWNSCALE.name()));
 }
 @Override
 public void triggerUpdateAllowedSubnets(Object object) {
   UpdateAllowedSubnetsRequest updateAllowedSubnetsRequest = (UpdateAllowedSubnetsRequest) object;
   UpdateAllowedSubnetsContext context =
       new UpdateAllowedSubnetsContext(updateAllowedSubnetsRequest);
   reactor.notify(
       FlowPhases.UPDATE_ALLOWED_SUBNETS.name(),
       eventFactory.createEvent(context, FlowPhases.UPDATE_ALLOWED_SUBNETS.name()));
 }
 @Override
 public void triggerForcedTermination(Object object) {
   StackDeleteRequest deleteRequest = (StackForcedDeleteRequest) object;
   DefaultFlowContext context =
       new DefaultFlowContext(deleteRequest.getStackId(), deleteRequest.getCloudPlatform());
   reactor.notify(
       FlowPhases.FORCED_TERMINATION.name(),
       eventFactory.createEvent(context, FlowPhases.FORCED_TERMINATION.name()));
 }
 @Override
 public void triggerStackStop(Object object) {
   StackStatusUpdateRequest statusUpdateRequest = (StackStatusUpdateRequest) object;
   StackStatusUpdateContext context =
       new StackStatusUpdateContext(
           statusUpdateRequest.getStackId(), statusUpdateRequest.getCloudPlatform(), false);
   reactor.notify(
       FlowPhases.STACK_STOP.name(),
       eventFactory.createEvent(context, FlowPhases.STACK_STOP.name()));
 }
 @PostConstruct
 public void init() {
   validateSelectors();
   LOGGER.info("Registering ClusterEventHandler");
   for (ClusterEventHandler handler : handlers) {
     String selector = EventSelectorUtil.selector(handler.type());
     LOGGER.info("Registering handler [{}] for selector [{}]", handler.getClass(), selector);
     eventBus.on($(selector), handler);
   }
 }
 @Override
 public void triggerClusterSync(Object object) {
   ClusterStatusUpdateRequest statusUpdateRequest = (ClusterStatusUpdateRequest) object;
   StackStatusUpdateContext context =
       new StackStatusUpdateContext(
           statusUpdateRequest.getStackId(), statusUpdateRequest.getCloudPlatform(), false);
   reactor.notify(
       FlowPhases.CLUSTER_SYNC.name(),
       eventFactory.createEvent(context, FlowPhases.CLUSTER_SYNC.name()));
 }
 @Override
 public void triggerClusterReInstall(Object object) {
   ProvisionRequest provisionRequest = (ProvisionRequest) object;
   ProvisioningContext context =
       new ProvisioningContext.Builder()
           .setDefaultParams(provisionRequest.getStackId(), provisionRequest.getCloudPlatform())
           .build();
   reactor.notify(
       FlowPhases.CLUSTER_RESET.name(),
       eventFactory.createEvent(context, FlowPhases.CLUSTER_RESET.name()));
 }
 @Override
 public void accept(Event<StartAmbariServicesRequest> event) {
   Long stackId = event.getData().getStackId();
   Selectable response;
   try {
     clusterServiceRunner.runAmbariServices(stackId);
     response = new StartAmbariServicesSuccess(stackId);
   } catch (Exception e) {
     response = new StartAmbariServicesFailed(stackId, e);
   }
   eventBus.notify(response.selector(), new Event(event.getHeaders(), response));
 }
 @Override
 public void triggerNext(Class sourceHandlerClass, Object payload, boolean success) {
   String key =
       success
           ? transitionKeyService.successKey(sourceHandlerClass)
           : transitionKeyService.failureKey(sourceHandlerClass);
   if (isTriggerKey(key)) {
     Event event = eventFactory.createEvent(payload, key);
     reactor.notify(key, event);
   } else {
     LOGGER.debug("The handler {} has no transitions.", sourceHandlerClass);
   }
 }
 @Override
 public void triggerClusterUserNamePasswordUpdate(Object object) {
   ClusterUserNamePasswordUpdateRequest request = (ClusterUserNamePasswordUpdateRequest) object;
   ClusterAuthenticationContext context =
       new ClusterAuthenticationContext(
           request.getStackId(),
           request.getCloudPlatform(),
           request.getNewUserName(),
           request.getNewPassword());
   reactor.notify(
       FlowPhases.CLUSTER_USERNAME_PASSWORD_UPDATE.name(),
       eventFactory.createEvent(context, FlowPhases.CLUSTER_USERNAME_PASSWORD_UPDATE.name()));
 }
 @Override
 public PlatformParameters getPlatformParameters(Stack stack) {
   LOGGER.debug("Get platform parameters for: {}", stack);
   CloudContext cloudContext = new CloudContext(stack);
   CloudCredential cloudCredential = credentialConverter.convert(stack.getCredential());
   PlatformParameterRequest parameterRequest =
       new PlatformParameterRequest(cloudContext, cloudCredential);
   eventBus.notify(parameterRequest.selector(), Event.wrap(parameterRequest));
   try {
     PlatformParameterResult res = parameterRequest.await();
     LOGGER.info("Platform parameter result: {}", res);
     if (res.getStatus().equals(EventStatus.FAILED)) {
       LOGGER.error("Failed to get platform parameters", res.getErrorDetails());
       throw new OperationException(res.getErrorDetails());
     }
     return res.getPlatformParameters();
   } catch (InterruptedException e) {
     LOGGER.error("Error while getting platform parameters: " + cloudContext, e);
     throw new OperationException(e);
   }
 }
 @Override
 public Set<String> removeInstances(
     Stack stack,
     String gateWayUserData,
     String coreUserData,
     Set<String> instanceIds,
     String instanceGroup) {
   LOGGER.debug("Assembling downscale stack event for stack: {}", stack);
   CloudContext cloudContext = new CloudContext(stack);
   CloudCredential cloudCredential = credentialConverter.convert(stack.getCredential());
   List<CloudResource> resources = cloudResourceConverter.convert(stack.getResources());
   List<CloudInstance> instances = new ArrayList<>();
   InstanceGroup group = stack.getInstanceGroupByInstanceGroupName(instanceGroup);
   for (InstanceMetaData metaData : group.getAllInstanceMetaData()) {
     if (instanceIds.contains(metaData.getInstanceId())) {
       CloudInstance cloudInstance = metadataConverter.convert(metaData);
       instances.add(cloudInstance);
     }
   }
   CloudStack cloudStack =
       cloudStackConverter.convert(stack, coreUserData, gateWayUserData, instanceIds);
   DownscaleStackRequest<DownscaleStackResult> downscaleRequest =
       new DownscaleStackRequest<>(
           cloudContext, cloudCredential, cloudStack, resources, instances);
   LOGGER.info("Triggering downscale stack event: {}", downscaleRequest);
   eventBus.notify(downscaleRequest.selector(), Event.wrap(downscaleRequest));
   try {
     DownscaleStackResult res = downscaleRequest.await();
     LOGGER.info("Downscale stack result: {}", res);
     if (res.getStatus().equals(EventStatus.FAILED)) {
       LOGGER.error("Failed to downscale the stack", res.getErrorDetails());
       throw new OperationException(res.getErrorDetails());
     }
     return instanceIds;
   } catch (InterruptedException e) {
     LOGGER.error("Error while downscaling the stack", e);
     throw new OperationException(e);
   }
 }
 @Override
 public String checkAndGetPlatformVariant(Stack stack) {
   LOGGER.debug("Get platform variant for: {}", stack);
   CloudContext cloudContext = new CloudContext(stack);
   CloudCredential cloudCredential = credentialConverter.convert(stack.getCredential());
   CheckPlatformVariantRequest checkPlatformVariantRequest =
       new CheckPlatformVariantRequest(cloudContext, cloudCredential);
   eventBus.notify(
       checkPlatformVariantRequest.selector(), Event.wrap(checkPlatformVariantRequest));
   try {
     CheckPlatformVariantResult res = checkPlatformVariantRequest.await();
     LOGGER.info("Platform variant result: {}", res);
     if (res.getStatus().equals(EventStatus.FAILED)) {
       LOGGER.error("Failed to get platform variant", res.getErrorDetails());
       throw new OperationException(res.getErrorDetails());
     }
     return res.getDefaultPlatformVariant();
   } catch (InterruptedException e) {
     LOGGER.error("Error while getting the platform variant: " + cloudContext, e);
     throw new OperationException(e);
   }
 }
 @Override
 public Set<Resource> addInstances(
     Stack stack,
     String gateWayUserData,
     String coreUserData,
     Integer adjustment,
     String instanceGroup) {
   LOGGER.debug("Assembling upscale stack event for stack: {}", stack);
   CloudContext cloudContext = new CloudContext(stack);
   CloudCredential cloudCredential = credentialConverter.convert(stack.getCredential());
   InstanceGroup group = stack.getInstanceGroupByInstanceGroupName(instanceGroup);
   group.setNodeCount(group.getNodeCount() + adjustment);
   CloudStack cloudStack = cloudStackConverter.convert(stack, coreUserData, gateWayUserData);
   instanceMetadataService.saveInstanceRequests(stack, cloudStack.getGroups());
   List<CloudResource> resources = cloudResourceConverter.convert(stack.getResources());
   UpscaleStackRequest<UpscaleStackResult> upscaleRequest =
       new UpscaleStackRequest<>(cloudContext, cloudCredential, cloudStack, resources);
   LOGGER.info("Triggering upscale stack event: {}", upscaleRequest);
   eventBus.notify(upscaleRequest.selector(), Event.wrap(upscaleRequest));
   try {
     UpscaleStackResult res = upscaleRequest.await();
     LOGGER.info("Upscale stack result: {}", res);
     List<CloudResourceStatus> results = res.getResults();
     updateNodeCount(stack.getId(), cloudStack.getGroups(), results, false);
     validateResourceResults(cloudContext, res);
     Set<Resource> resourceSet = transformResults(results, stack);
     if (resourceSet.isEmpty()) {
       throw new OperationException(
           "Failed to upscale the cluster since all create request failed: "
               + results.get(0).getStatusReason());
     }
     return resourceSet;
   } catch (InterruptedException e) {
     LOGGER.error("Error while upscaling the stack", e);
     throw new OperationException(e);
   }
 }
 @Override
 public void triggerProvisioning(Object object) {
   ProvisionRequest provisionRequest = (ProvisionRequest) object;
   reactor.notify(FlowPhases.PROVISIONING_SETUP.name(), Event.wrap(provisionRequest));
 }
 @Override
 public void pessoaCadastrada(Pessoa pessoa) {
   eventBus.notify("indexadorEventBus", Event.wrap(pessoa));
 }