package com.sequenceiq.cloudbreak.core.bootstrap.service;
import static com.sequenceiq.cloudbreak.domain.ClusterAttributes.CUSTOM_QUEUE;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.inject.Inject;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import com.sequenceiq.cloudbreak.common.type.ComponentType;
import com.sequenceiq.cloudbreak.core.CloudbreakException;
import com.sequenceiq.cloudbreak.core.bootstrap.config.ContainerConfigBuilder;
import com.sequenceiq.cloudbreak.core.bootstrap.service.container.ContainerOrchestratorResolver;
import com.sequenceiq.cloudbreak.domain.Component;
import com.sequenceiq.cloudbreak.domain.Stack;
import com.sequenceiq.cloudbreak.domain.json.Json;
import com.sequenceiq.cloudbreak.orchestrator.container.ContainerOrchestrator;
import com.sequenceiq.cloudbreak.orchestrator.container.DockerContainer;
import com.sequenceiq.cloudbreak.orchestrator.model.ContainerConfig;
import com.sequenceiq.cloudbreak.service.CloudbreakServiceException;
import com.sequenceiq.cloudbreak.service.ComponentConfigProvider;
@Service
public class ContainerConfigService {
private static final Logger LOGGER = LoggerFactory.getLogger(ContainerConfigService.class);
@Value("${cb.docker.container.yarn.ambari.agent:}")
private String yarnAmbariAgent;
@Value("${cb.docker.container.yarn.ambari.server:}")
private String yarnAmbariServer;
@Value("${cb.docker.container.registrator:}")
private String registratorDockerImageName;
@Value("${cb.docker.container.docker.consul.watch.plugn:}")
private String consulWatchPlugnDockerImageName;
@Value("${cb.docker.container.yarn.ambari.db:}")
private String yarnPostgresDockerImageName;
@Value("${cb.docker.container.kerberos:}")
private String kerberosDockerImageName;
@Value("${cb.docker.container.logrotate:}")
private String logrotateDockerImageName;
@Value("${cb.docker.container.munchausen:}")
private String munchausenImageName;
@Value("${cb.docker.container.haveged:}")
private String havegedImageName;
@Value("${cb.docker.container.ldap:}")
private String ldapImageName;
@Value("${cb.docker.container.shipyard:}")
private String shipyardImageName;
@Value("${cb.docker.container.shipyard.db:}")
private String rethinkDbImageName;
@Inject
private ComponentConfigProvider componentConfigProvider;
@Inject
private ContainerOrchestratorResolver containerOrchestratorResolver;
public ContainerConfig get(Stack stack, DockerContainer dc) {
try {
Component component = componentConfigProvider.getComponent(stack.getId(), ComponentType.CONTAINER, dc.name());
if (component == null) {
component = create(stack, dc);
LOGGER.info("Container component definition created: {}", component);
} else {
LOGGER.info("Container component definition found in database: {}", component);
}
return component.getAttributes().get(ContainerConfig.class);
} catch (CloudbreakException | IOException e) {
throw new CloudbreakServiceException(String.format("Failed to parse component ContainerConfig for stack: %d, container: %s", stack.getId(),
dc.getName()));
}
}
private Component create(Stack stack, DockerContainer dc) throws CloudbreakException {
try {
ContainerConfig config;
ContainerOrchestrator orchestrator = containerOrchestratorResolver.get(stack.getOrchestrator().getType());
Map<String, String> customContainerConfig = getCustomContainerConfig(stack);
Optional<String> customContainerName = Optional.ofNullable(customContainerConfig.get(dc.name()));
Optional<String> customQueue = getCustomQueue(stack);
switch (dc) {
case AMBARI_SERVER:
config = new ContainerConfigBuilder.Builder(orchestrator.ambariServerContainer(customContainerName), customQueue).build();
break;
case AMBARI_AGENT:
config = new ContainerConfigBuilder.Builder(orchestrator.ambariClientContainer(customContainerName), customQueue).build();
break;
case AMBARI_DB:
config = new ContainerConfigBuilder.Builder(orchestrator.ambariDbContainer(customContainerName), customQueue).build();
break;
case KERBEROS:
config = new ContainerConfigBuilder.Builder(kerberosDockerImageName, customQueue).build();
break;
case REGISTRATOR:
config = new ContainerConfigBuilder.Builder(registratorDockerImageName, customQueue).build();
break;
case MUNCHAUSEN:
config = new ContainerConfigBuilder.Builder(munchausenImageName, customQueue).build();
break;
case CONSUL_WATCH:
config = new ContainerConfigBuilder.Builder(consulWatchPlugnDockerImageName, customQueue).build();
break;
case LOGROTATE:
config = new ContainerConfigBuilder.Builder(logrotateDockerImageName, customQueue).build();
break;
case HAVEGED:
config = new ContainerConfigBuilder.Builder(havegedImageName, customQueue).build();
break;
case LDAP:
config = new ContainerConfigBuilder.Builder(ldapImageName, customQueue).build();
break;
case SHIPYARD:
config = new ContainerConfigBuilder.Builder(shipyardImageName, customQueue).build();
break;
case SHIPYARD_DB:
config = new ContainerConfigBuilder.Builder(rethinkDbImageName, customQueue).build();
break;
default:
throw new CloudbreakServiceException(String.format("No configuration exist for %s", dc));
}
Component component = new Component(ComponentType.CONTAINER, dc.name(), new Json(config), stack);
return componentConfigProvider.store(component);
} catch (IOException e) {
throw new CloudbreakServiceException(String.format("Failed to parse component ContainerConfig for stack: %d, container: %s",
stack.getId(), dc.getName()));
}
}
private Map<String, String> getCustomContainerConfig(Stack stack) {
Json customContainerDefinition = stack.getCluster().getCustomContainerDefinition();
if (customContainerDefinition != null && StringUtils.isNoneEmpty(customContainerDefinition.getValue())) {
try {
return customContainerDefinition.get(Map.class);
} catch (IOException e) {
LOGGER.error("Failed to add customContainerDefinition to response", e);
return new HashMap<>();
}
}
return new HashMap<>();
}
private Optional<String> getCustomQueue(Stack stack) {
return Optional.ofNullable((String) stack.getCluster().getAttributes().getMap().get(CUSTOM_QUEUE.name()));
}
}