package com.sequenceiq.periscope.rest.controller;
import java.util.List;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.stereotype.Component;
import com.sequenceiq.periscope.api.endpoint.ClusterEndpoint;
import com.sequenceiq.periscope.api.model.AmbariJson;
import com.sequenceiq.periscope.api.model.ClusterJson;
import com.sequenceiq.periscope.api.model.ClusterState;
import com.sequenceiq.periscope.api.model.ScalingStatus;
import com.sequenceiq.periscope.api.model.StateJson;
import com.sequenceiq.periscope.domain.Ambari;
import com.sequenceiq.periscope.domain.Cluster;
import com.sequenceiq.periscope.domain.History;
import com.sequenceiq.periscope.domain.PeriscopeUser;
import com.sequenceiq.periscope.log.MDCBuilder;
import com.sequenceiq.periscope.model.AmbariStack;
import com.sequenceiq.periscope.notification.HttpNotificationSender;
import com.sequenceiq.periscope.rest.converter.AmbariConverter;
import com.sequenceiq.periscope.rest.converter.ClusterConverter;
import com.sequenceiq.periscope.service.AuthenticatedUserService;
import com.sequenceiq.periscope.service.ClusterService;
import com.sequenceiq.periscope.service.HistoryService;
import com.sequenceiq.periscope.service.security.ClusterSecurityService;
@Component
public class ClusterController implements ClusterEndpoint {
private static final Logger LOGGER = LoggerFactory.getLogger(ClusterController.class);
@Inject
private ClusterService clusterService;
@Inject
private AmbariConverter ambariConverter;
@Inject
private ClusterConverter clusterConverter;
@Inject
private ClusterSecurityService clusterSecurityService;
@Inject
private AuthenticatedUserService authenticatedUserService;
@Inject
private HistoryService historyService;
@Inject
private HttpNotificationSender notificationSender;
@Override
public ClusterJson addCluster(AmbariJson ambariServer) {
PeriscopeUser user = authenticatedUserService.getPeriscopeUser();
MDCBuilder.buildUserMdcContext(user);
return setCluster(user, ambariServer, null);
}
@Override
public ClusterJson modifyCluster(AmbariJson ambariServer, Long clusterId) {
PeriscopeUser user = authenticatedUserService.getPeriscopeUser();
MDCBuilder.buildMdcContext(user, clusterId);
return setCluster(user, ambariServer, clusterId);
}
@Override
public List<ClusterJson> getClusters() {
PeriscopeUser user = authenticatedUserService.getPeriscopeUser();
MDCBuilder.buildUserMdcContext(user);
List<Cluster> clusters = clusterService.findAllByUser(user);
return clusterConverter.convertAllToJson(clusters);
}
@Override
public ClusterJson getCluster(Long clusterId) {
PeriscopeUser user = authenticatedUserService.getPeriscopeUser();
MDCBuilder.buildMdcContext(user, clusterId);
return createClusterJsonResponse(clusterService.findOneById(clusterId));
}
@Override
public void deleteCluster(Long clusterId) {
PeriscopeUser user = authenticatedUserService.getPeriscopeUser();
MDCBuilder.buildMdcContext(user, clusterId);
clusterService.removeOne(clusterId);
}
@Override
public ClusterJson setState(Long clusterId, StateJson stateJson) {
PeriscopeUser user = authenticatedUserService.getPeriscopeUser();
MDCBuilder.buildMdcContext(user, clusterId);
Cluster cluster = clusterService.setState(clusterId, stateJson.getState());
createHistoryAndNotification(cluster);
return createClusterJsonResponse(cluster);
}
private ClusterJson createClusterJsonResponse(Cluster cluster) {
return clusterConverter.convert(cluster);
}
private ClusterJson setCluster(PeriscopeUser user, AmbariJson json, Long clusterId) {
Ambari ambari = ambariConverter.convert(json);
boolean access = clusterSecurityService.hasAccess(user, ambari, json.getStackId());
if (!access) {
String host = ambari.getHost();
LOGGER.info("Illegal access to Ambari cluster '{}' from user '{}'", host, user.getEmail());
throw new AccessDeniedException(String.format("Accessing Ambari cluster '%s' is not allowed", host));
} else {
Cluster cluster;
if (json.getStackId() != null && ClusterState.PENDING.equals(json.getClusterState())) {
AmbariStack ambariStack = new AmbariStack(ambari, json.getStackId(), null);
cluster = clusterService.create(user, ambariStack, json.getClusterState());
} else {
AmbariStack resolvedAmbari = clusterSecurityService.tryResolve(ambari);
if (clusterId == null) {
cluster = clusterService.create(user, resolvedAmbari, null);
} else {
cluster = clusterService.update(clusterId, resolvedAmbari);
}
}
createHistoryAndNotification(cluster);
return createClusterJsonResponse(cluster);
}
}
private void createHistoryAndNotification(Cluster cluster) {
History history;
if (ClusterState.RUNNING.equals(cluster.getState())) {
history = historyService.createEntry(ScalingStatus.ENABLED, "Autoscaling has been enabled for the cluster.", 0, cluster);
} else {
history = historyService.createEntry(ScalingStatus.DISABLED, "Autoscaling has been disabled for the cluster.", 0, cluster);
}
notificationSender.send(history);
}
}