package com.sequenceiq.cloudbreak.converter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import javax.inject.Inject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.convert.TypeDescriptor;
import org.springframework.stereotype.Component;
import com.sequenceiq.cloudbreak.api.model.CloudbreakDetailsJson;
import com.sequenceiq.cloudbreak.api.model.ClusterResponse;
import com.sequenceiq.cloudbreak.api.model.CredentialResponse;
import com.sequenceiq.cloudbreak.api.model.FailurePolicyResponse;
import com.sequenceiq.cloudbreak.api.model.FlexSubscriptionResponse;
import com.sequenceiq.cloudbreak.api.model.ImageJson;
import com.sequenceiq.cloudbreak.api.model.InstanceGroupResponse;
import com.sequenceiq.cloudbreak.api.model.NetworkResponse;
import com.sequenceiq.cloudbreak.api.model.OrchestratorResponse;
import com.sequenceiq.cloudbreak.api.model.StackResponse;
import com.sequenceiq.cloudbreak.cloud.model.AmbariRepo;
import com.sequenceiq.cloudbreak.cloud.model.CloudbreakDetails;
import com.sequenceiq.cloudbreak.cloud.model.HDPRepo;
import com.sequenceiq.cloudbreak.cloud.model.Image;
import com.sequenceiq.cloudbreak.cloud.model.StackTemplate;
import com.sequenceiq.cloudbreak.common.type.ResourceType;
import com.sequenceiq.cloudbreak.core.CloudbreakImageNotFoundException;
import com.sequenceiq.cloudbreak.domain.InstanceGroup;
import com.sequenceiq.cloudbreak.domain.Resource;
import com.sequenceiq.cloudbreak.domain.Stack;
import com.sequenceiq.cloudbreak.domain.json.Json;
import com.sequenceiq.cloudbreak.service.ClusterComponentConfigProvider;
import com.sequenceiq.cloudbreak.service.ComponentConfigProvider;
import com.sequenceiq.cloudbreak.service.image.ImageService;
@Component
public class StackToJsonConverter extends AbstractConversionServiceAwareConverter<Stack, StackResponse> {
private static final Logger LOGGER = LoggerFactory.getLogger(StackToJsonConverter.class);
@Inject
private ImageService imageService;
@Inject
private ComponentConfigProvider componentConfigProvider;
@Inject
private ClusterComponentConfigProvider clusterComponentConfigProvider;
@Override
public StackResponse convert(Stack source) {
StackResponse stackJson = new StackResponse();
try {
Image image = imageService.getImage(source.getId());
stackJson.setImage(getConversionService().convert(image, ImageJson.class));
} catch (CloudbreakImageNotFoundException exc) {
LOGGER.info(exc.getMessage());
}
stackJson.setName(source.getName());
stackJson.setOwner(source.getOwner());
stackJson.setAccount(source.getAccount());
stackJson.setPublicInAccount(source.isPublicInAccount());
stackJson.setId(source.getId());
if (source.getCredential() == null) {
stackJson.setCloudPlatform(null);
stackJson.setCredentialId(null);
} else {
stackJson.setCloudPlatform(source.cloudPlatform());
stackJson.setCredentialId(source.getCredential().getId());
stackJson.setCredential(getConversionService().convert(source.getCredential(), CredentialResponse.class));
}
stackJson.setStatus(source.getStatus());
stackJson.setStatusReason(source.getStatusReason());
stackJson.setRegion(source.getRegion());
stackJson.setAvailabilityZone(source.getAvailabilityZone());
stackJson.setOnFailureAction(source.getOnFailureActionAction());
List<InstanceGroupResponse> templateGroups = new ArrayList<>();
templateGroups.addAll(convertInstanceGroups(source.getInstanceGroups()));
stackJson.setInstanceGroups(templateGroups);
if (source.getCluster() != null) {
stackJson.setCluster(getConversionService().convert(source.getCluster(), ClusterResponse.class));
} else {
stackJson.setCluster(new ClusterResponse());
}
if (source.getFailurePolicy() != null) {
stackJson.setFailurePolicy(getConversionService().convert(source.getFailurePolicy(), FailurePolicyResponse.class));
}
if (source.getNetwork() == null) {
stackJson.setNetworkId(null);
} else {
stackJson.setNetworkId(source.getNetwork().getId());
stackJson.setNetwork(getConversionService().convert(source.getNetwork(), NetworkResponse.class));
}
stackJson.setRelocateDocker(source.getRelocateDocker());
stackJson.setParameters(new HashMap(source.getParameters()));
stackJson.setPlatformVariant(source.getPlatformVariant());
if (source.getOrchestrator() != null) {
stackJson.setOrchestrator(getConversionService().convert(source.getOrchestrator(), OrchestratorResponse.class));
}
stackJson.setCreated(source.getCreated());
stackJson.setGatewayPort(source.getGatewayPort());
List<Resource> resourcesByType = source.getResourcesByType(ResourceType.S3_ACCESS_ROLE_ARN);
Optional<Resource> accessRoleArnOptional = resourcesByType.stream().findFirst();
if (accessRoleArnOptional.isPresent()) {
String s3AccessRoleArn = accessRoleArnOptional.get().getResourceName();
stackJson.setS3AccessRoleArn(s3AccessRoleArn);
}
putSubnetIdIntoResponse(source, stackJson);
putVpcIdIntoResponse(source, stackJson);
convertComponentConfig(stackJson, source);
convertTags(stackJson, source.getTags());
addFlexSubscription(stackJson, source);
return stackJson;
}
private void putSubnetIdIntoResponse(Stack source, StackResponse stackJson) {
List<Resource> resourcesByType = source.getResourcesByType(ResourceType.AWS_SUBNET);
Optional<Resource> awsSubnet = resourcesByType.stream().findFirst();
if (awsSubnet.isPresent()) {
String subnetId = awsSubnet.get().getResourceName();
stackJson.getParameters().put(ResourceType.AWS_SUBNET.name(), subnetId);
}
}
private void putVpcIdIntoResponse(Stack source, StackResponse stackJson) {
List<Resource> resourcesByType = source.getResourcesByType(ResourceType.AWS_VPC);
Optional<Resource> awsVpc = resourcesByType.stream().findFirst();
if (awsVpc.isPresent()) {
String vpcId = awsVpc.get().getResourceName();
stackJson.getParameters().put(ResourceType.AWS_VPC.name(), vpcId);
}
}
private void convertTags(StackResponse stackJson, Json tag) {
try {
Map<String, Object> tags = new HashMap<>();
if (tag != null) {
if (tag.getValue() != null) {
stackJson.setTags(tag.get(Map.class));
} else {
stackJson.setTags(tags);
}
} else {
stackJson.setTags(new HashMap<>());
}
} catch (Exception e) {
LOGGER.error("Failed to convert dynamic tags.", e);
}
}
private StackResponse convertComponentConfig(StackResponse stackJson, Stack source) {
try {
if (source.getCluster() != null) {
HDPRepo hdpRepo = clusterComponentConfigProvider.getHDPRepo(source.getCluster().getId());
if (hdpRepo != null) {
stackJson.setHdpVersion(hdpRepo.getHdpVersion());
}
AmbariRepo ambariRepo = clusterComponentConfigProvider.getAmbariRepo(source.getCluster().getId());
if (ambariRepo != null) {
stackJson.setAmbariVersion(ambariRepo.getVersion());
}
}
CloudbreakDetails cloudbreakDetails = componentConfigProvider.getCloudbreakDetails(source.getId());
if (cloudbreakDetails != null) {
stackJson.setCloudbreakDetails(getConversionService().convert(cloudbreakDetails, CloudbreakDetailsJson.class));
}
StackTemplate stackTemplate = componentConfigProvider.getStackTemplate(source.getId());
if (stackTemplate != null) {
stackJson.setStackTemplate(stackTemplate.getTemplate());
}
} catch (Exception e) {
LOGGER.error("Failed to convert dynamic component.", e);
}
return stackJson;
}
private Set<InstanceGroupResponse> convertInstanceGroups(Set<InstanceGroup> instanceGroups) {
return (Set<InstanceGroupResponse>) getConversionService().convert(instanceGroups, TypeDescriptor.forObject(instanceGroups),
TypeDescriptor.collection(Set.class, TypeDescriptor.valueOf(InstanceGroupResponse.class)));
}
private void addFlexSubscription(StackResponse stackJson, Stack source) {
if (source.getFlexSubscription() != null) {
try {
FlexSubscriptionResponse flexSubscription = getConversionService().convert(source.getFlexSubscription(), FlexSubscriptionResponse.class);
stackJson.setFlexSubscription(flexSubscription);
} catch (Exception ex) {
LOGGER.warn("Flex subscription could not be added to stack response.", ex);
}
}
}
}