package com.sequenceiq.cloudbreak.service.decorator;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;
import javax.inject.Inject;
import org.springframework.core.convert.ConversionService;
import org.springframework.stereotype.Component;
import com.sequenceiq.cloudbreak.api.model.BlueprintRequest;
import com.sequenceiq.cloudbreak.api.model.HostGroupRequest;
import com.sequenceiq.cloudbreak.api.model.LdapConfigRequest;
import com.sequenceiq.cloudbreak.api.model.RDSConfigJson;
import com.sequenceiq.cloudbreak.api.model.SssdConfigRequest;
import com.sequenceiq.cloudbreak.controller.BadRequestException;
import com.sequenceiq.cloudbreak.controller.validation.blueprint.BlueprintValidator;
import com.sequenceiq.cloudbreak.controller.validation.ldapconfig.LdapConfigValidator;
import com.sequenceiq.cloudbreak.domain.Blueprint;
import com.sequenceiq.cloudbreak.domain.CbUser;
import com.sequenceiq.cloudbreak.domain.Cluster;
import com.sequenceiq.cloudbreak.domain.HostGroup;
import com.sequenceiq.cloudbreak.domain.LdapConfig;
import com.sequenceiq.cloudbreak.domain.RDSConfig;
import com.sequenceiq.cloudbreak.domain.SssdConfig;
import com.sequenceiq.cloudbreak.domain.Stack;
import com.sequenceiq.cloudbreak.service.blueprint.BlueprintService;
import com.sequenceiq.cloudbreak.service.ldapconfig.LdapConfigService;
import com.sequenceiq.cloudbreak.service.rdsconfig.RdsConfigService;
import com.sequenceiq.cloudbreak.service.sssdconfig.SssdConfigService;
import com.sequenceiq.cloudbreak.service.stack.StackService;
@Component
public class ClusterDecorator implements Decorator<Cluster> {
private enum DecorationData {
STACK_ID,
USER,
BLUEPRINT_ID,
HOSTGROUP_JSONS,
VALIDATE_BLUEPRINT,
SSSDCONFIG_ID,
RDSCONFIG_ID,
LDAP_CONFIG_ID,
BLUEPRINT,
SSSDCONFIG,
RDSCONFIG,
LDAP_CONFIG;
}
@Inject
private BlueprintService blueprintService;
@Inject
private BlueprintValidator blueprintValidator;
@Inject
private StackService stackService;
@Inject
private ConversionService conversionService;
@Inject
private HostGroupDecorator hostGroupDecorator;
@Inject
private SssdConfigService sssdConfigService;
@Inject
private RdsConfigService rdsConfigService;
@Inject
private LdapConfigService ldapConfigService;
@Inject
private LdapConfigValidator ldapConfigValidator;
@Override
public Cluster decorate(Cluster subject, Object... data) {
if (null == data || data.length != DecorationData.values().length) {
throw new IllegalArgumentException("Invalid decoration data provided. Cluster: " + subject.getName());
}
Long stackId = (Long) data[DecorationData.STACK_ID.ordinal()];
CbUser user = (CbUser) data[DecorationData.USER.ordinal()];
Long blueprintId = (Long) data[DecorationData.BLUEPRINT_ID.ordinal()];
Long ldapConfigId = (Long) data[DecorationData.LDAP_CONFIG_ID.ordinal()];
Set<HostGroupRequest> hostGroupsJsons = (Set<HostGroupRequest>) data[DecorationData.HOSTGROUP_JSONS.ordinal()];
BlueprintRequest requestBlueprint = (BlueprintRequest) data[DecorationData.BLUEPRINT.ordinal()];
SssdConfigRequest requestSssd = (SssdConfigRequest) data[DecorationData.SSSDCONFIG.ordinal()];
Set<RDSConfigJson> requestRdsConfigs = (Set<RDSConfigJson>) data[DecorationData.RDSCONFIG.ordinal()];
LdapConfigRequest ldapConfigRequest = (LdapConfigRequest) data[DecorationData.LDAP_CONFIG.ordinal()];
Set<Long> rdsConfigIds = (Set<Long>) data[DecorationData.RDSCONFIG_ID.ordinal()];
Long sssdConfigId = (Long) data[DecorationData.SSSDCONFIG_ID.ordinal()];
Stack stack = stackService.getById(stackId);
if (blueprintId != null) {
subject.setBlueprint(blueprintService.get(blueprintId));
} else if (requestBlueprint != null) {
Blueprint blueprint = conversionService.convert(requestBlueprint, Blueprint.class);
blueprint.setPublicInAccount(stack.isPublicInAccount());
blueprint = blueprintService.create(user, blueprint, new ArrayList<>());
subject.setBlueprint(blueprint);
} else {
throw new BadRequestException("Blueprint does not configured for the cluster!");
}
subject.setHostGroups(convertHostGroupsFromJson(stack, user, subject, hostGroupsJsons));
boolean validate = (boolean) data[DecorationData.VALIDATE_BLUEPRINT.ordinal()];
if (validate) {
Blueprint blueprint = null;
if (blueprintId != null) {
blueprint = blueprintService.get(blueprintId);
} else if (requestBlueprint != null) {
blueprint = subject.getBlueprint();
}
blueprintValidator.validateBlueprintForStack(blueprint, subject.getHostGroups(), stack.getInstanceGroups());
}
subject.setTopologyValidation(validate);
prepareSssd(subject, user, sssdConfigId, requestSssd, stack);
prepareRds(subject, user, rdsConfigIds, requestRdsConfigs, stack);
prepareLdap(subject, user, ldapConfigId, ldapConfigRequest, stack);
return subject;
}
private void prepareSssd(Cluster subject, CbUser user, Long sssdConfigId, SssdConfigRequest requestSssd, Stack stack) {
if (sssdConfigId != null) {
SssdConfig config = sssdConfigService.get(sssdConfigId);
subject.setSssdConfig(config);
} else if (requestSssd != null) {
SssdConfig sssdConfig = conversionService.convert(requestSssd, SssdConfig.class);
sssdConfig.setPublicInAccount(stack.isPublicInAccount());
sssdConfig = sssdConfigService.create(user, sssdConfig);
subject.setSssdConfig(sssdConfig);
}
}
private void prepareLdap(Cluster subject, CbUser user, Long ldapConfigId, LdapConfigRequest ldapConfigRequest, Stack stack) {
if (ldapConfigId != null) {
LdapConfig ldapConfig = ldapConfigService.get(ldapConfigId);
subject.setLdapConfig(ldapConfig);
} else if (ldapConfigRequest != null) {
LdapConfig ldapConfig = conversionService.convert(ldapConfigRequest, LdapConfig.class);
ldapConfig.setPublicInAccount(stack.isPublicInAccount());
ldapConfigValidator.validateLdapConnection(ldapConfig);
ldapConfig = ldapConfigService.create(user, ldapConfig);
subject.setLdapConfig(ldapConfig);
}
}
private void prepareRds(Cluster subject, CbUser user, Set<Long> rdsConfigIds, Set<RDSConfigJson> requestRdsConfigs, Stack stack) {
subject.setRdsConfigs(new HashSet<>());
if (rdsConfigIds != null && !rdsConfigIds.isEmpty()) {
for (Long rdsConfigId : rdsConfigIds) {
RDSConfig rdsConfig = rdsConfigService.get(rdsConfigId);
subject.getRdsConfigs().add(rdsConfig);
}
} else if (requestRdsConfigs != null && !requestRdsConfigs.isEmpty()) {
for (RDSConfigJson requestRdsConfig : requestRdsConfigs) {
RDSConfig rdsConfig = conversionService.convert(requestRdsConfig, RDSConfig.class);
rdsConfig.setPublicInAccount(stack.isPublicInAccount());
rdsConfig = rdsConfigService.create(user, rdsConfig);
subject.getRdsConfigs().add(rdsConfig);
}
}
}
private Set<HostGroup> convertHostGroupsFromJson(Stack stack, CbUser user, Cluster cluster, Set<HostGroupRequest> hostGroupsJsons) {
Set<HostGroup> hostGroups = new HashSet<>();
for (HostGroupRequest json : hostGroupsJsons) {
HostGroup hostGroup = conversionService.convert(json, HostGroup.class);
hostGroup.setCluster(cluster);
hostGroup = hostGroupDecorator.decorate(hostGroup, stack.getId(), user, json.getConstraint(), json.getRecipeIds(),
true, json.getRecipes(), stack.isPublicInAccount());
hostGroups.add(hostGroup);
}
return hostGroups;
}
}