package com.sequenceiq.cloudbreak.shell.model;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.inject.Inject;
import org.springframework.stereotype.Component;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.common.collect.Lists;
import com.sequenceiq.cloudbreak.api.model.AmbariDatabaseDetailsJson;
import com.sequenceiq.cloudbreak.api.model.BlueprintResponse;
import com.sequenceiq.cloudbreak.api.model.ConstraintTemplateResponse;
import com.sequenceiq.cloudbreak.api.model.CredentialResponse;
import com.sequenceiq.cloudbreak.api.model.FileSystemType;
import com.sequenceiq.cloudbreak.api.model.InstanceGroupResponse;
import com.sequenceiq.cloudbreak.api.model.StackResponse;
import com.sequenceiq.cloudbreak.api.model.TemplateResponse;
import com.sequenceiq.cloudbreak.api.model.VmTypeJson;
import com.sequenceiq.cloudbreak.client.CloudbreakClient;
import com.sequenceiq.cloudbreak.shell.commands.provider.AzureCommands;
import com.sequenceiq.cloudbreak.shell.transformer.ExceptionTransformer;
import com.sequenceiq.cloudbreak.shell.transformer.OutputTransformer;
import com.sequenceiq.cloudbreak.shell.transformer.ResponseTransformer;
@Component
public class ShellContext {
private static final String ACCESSIBLE = "accessible";
private Map<String, Collection<String>> platformToVariants;
private Map<String, Collection<String>> regions;
private Map<String, Map<String, Collection<String>>> availabilityZones;
private Map<String, Map<String, Collection<VmTypeJson>>> vmTypesPerZones = new HashMap<>();
private Map<String, Map<String, String>> defaultVmTypePerZones = new HashMap<>();
private Map<String, Collection<String>> volumeTypes;
private Map<String, List<Map<String, String>>> instanceTypes;
private Map<String, Collection<String>> orchestrators;
private Focus focus;
private Hints hint;
private String byosOrchestrator;
private String byosEndpoint;
private Map<PropertyKey, String> properties = new HashMap<>();
private Map<String, InstanceGroupEntry> instanceGroups = new HashMap<>();
private Map<String, HostgroupEntry> hostGroups = new HashMap<>();
private Set<String> activeHostGroups = new HashSet<>();
private Set<String> activeInstanceGroups = new HashSet<>();
private Set<String> activeTemplates = new HashSet<>();
private Set<String> activeTemplateNames = new HashSet<>();
private Map<Long, TemplateResponse> templateMap = new HashMap<>();
private String activeCloudPlatform;
private Map<Long, String> networksByProvider = new HashMap<>();
private Map<Long, String> securityGroups = new HashMap<>();
private Map<Long, String> rdsConfigs = new HashMap<>();
private Map<String, AvailabilitySetEntry> azureAvailabilitySets = new HashMap<>();
private Long activeNetworkId;
private FileSystemType fileSystemType;
private Map<String, Object> fileSystemParameters = new HashMap<>();
private Map<Long, String> ldapConfigs = new HashMap<>();
private Boolean defaultFileSystem;
private Long selectedMarathonStackId;
private String selectedMarathonStackName;
private Set<String> constraintTemplates = new HashSet<>();
private Set<String> enabledPlatforms = new HashSet<>();
private Map<String, MarathonHostgroupEntry> marathonHostgroups = new HashMap<>();
private Long selectedYarnStackId;
private String selectedYarnStackName;
private Map<String, YarnHostgroupEntry> yarnHostgroups = new HashMap<>();
private AmbariDatabaseDetailsJson ambariDatabaseDetailsJson;
@Inject
private CloudbreakClient cloudbreakClient;
@Inject
private ResponseTransformer responseTransformer;
@Inject
private ExceptionTransformer exceptionTransformer;
@Inject
private ObjectMapper objectMapper;
@Inject
private OutputTransformer outputTransformer;
public ShellContext() {
this.focus = getRootFocus();
this.hint = Hints.NONE;
this.instanceGroups = new HashMap<>();
this.hostGroups = new HashMap<>();
this.activeHostGroups = new HashSet<>();
this.activeInstanceGroups = new HashSet<>();
this.constraintTemplates = new HashSet<>();
this.marathonHostgroups = new HashMap<>();
this.yarnHostgroups = new HashMap<>();
this.azureAvailabilitySets = new HashMap<>();
}
public ResponseTransformer responseTransformer() {
return responseTransformer;
}
public ExceptionTransformer exceptionTransformer() {
return exceptionTransformer;
}
public CloudbreakClient cloudbreakClient() {
return cloudbreakClient;
}
public OutputTransformer outputTransformer() {
return outputTransformer;
}
public ObjectMapper objectMapper() {
return objectMapper;
}
public boolean isStackAvailable() {
return isPropertyAvailable(PropertyKey.STACK_ID);
}
public void addStack(String id, String name) {
addProperty(PropertyKey.STACK_ID, id);
addProperty(PropertyKey.STACK_NAME, name);
setStackAccessible();
}
public void resetFileSystemConfiguration() {
this.fileSystemParameters = new HashMap<>();
this.defaultFileSystem = null;
this.defaultFileSystem = null;
}
public String getActiveCloudPlatform() {
return this.activeCloudPlatform == null ? "" : this.activeCloudPlatform;
}
public boolean isAzureActiveCredential() {
return AzureCommands.PLATFORM.equals(getActiveCloudPlatform());
}
public void removeStack() {
removeProperty(PropertyKey.STACK_ID);
}
public Map<String, InstanceGroupEntry> getInstanceGroups() {
return this.instanceGroups;
}
public Map<String, HostgroupEntry> getHostGroups() {
return hostGroups;
}
public Map<String, InstanceGroupEntry> putInstanceGroup(String name, InstanceGroupEntry value) {
this.instanceGroups.put(name, value);
return this.instanceGroups;
}
public Map<String, HostgroupEntry> putHostGroup(String name, HostgroupEntry hostgroupEntry) {
this.hostGroups.put(name, hostgroupEntry);
return this.hostGroups;
}
public Set<String> getActiveTemplates() {
return activeTemplates;
}
public Set<String> getActiveTemplateNames() {
return activeTemplateNames;
}
public Map<Long, TemplateResponse> getTemplateMap() {
return templateMap;
}
public boolean isBlueprintAvailable() {
return isPropertyAvailable(PropertyKey.BLUEPRINT_ID);
}
public void addBlueprint(String id) throws Exception {
if (getStackId() == null) {
this.instanceGroups = new HashMap<>();
this.activeInstanceGroups = new HashSet<>();
}
this.hostGroups = new HashMap<>();
this.activeHostGroups = new HashSet<>();
String blueprintText = getBlueprintText(id);
JsonNode hostGroups = objectMapper.readTree(blueprintText.getBytes()).get("host_groups");
for (JsonNode hostGroup : hostGroups) {
activeHostGroups.add(hostGroup.get("name").asText());
if (getStackId() == null) {
activeInstanceGroups.add(hostGroup.get("name").asText());
}
}
addProperty(PropertyKey.BLUEPRINT_ID, id);
setBlueprintAccessible();
}
public String getBlueprintText() {
return getBlueprintText(getBlueprintId());
}
public void prepareInstanceGroups(StackResponse stack) {
this.instanceGroups = new HashMap<>();
this.activeInstanceGroups = new HashSet<>();
for (InstanceGroupResponse instanceGroup : stack.getInstanceGroups()) {
this.activeInstanceGroups.add(instanceGroup.getGroup());
instanceGroups.put(
instanceGroup.getGroup(),
new InstanceGroupEntry(
instanceGroup.getTemplateId(),
instanceGroup.getSecurityGroupId(),
instanceGroup.getNodeCount(),
instanceGroup.getType().name(),
instanceGroup.getParameters()
)
);
}
}
public Long getSelectedMarathonStackId() {
return selectedMarathonStackId;
}
public String getSelectedMarathonStackName() {
return selectedMarathonStackName;
}
public void setSelectedMarathonStackName(String selectedMarathonStackName) {
this.selectedMarathonStackName = selectedMarathonStackName;
}
public boolean isSelectedMarathonStackAvailable() {
return selectedMarathonStackId != null;
}
public void resetSelectedMarathonStackId() {
selectedMarathonStackId = null;
}
public void setSelectedMarathonStackId(Long selectedMarathonStackId) {
this.selectedMarathonStackId = selectedMarathonStackId;
}
public void resetMarathonHostGroups() {
this.marathonHostgroups = new HashMap<>();
}
public Long getSelectedYarnStackId() {
return selectedYarnStackId;
}
public String getSelectedYarnStackName() {
return selectedYarnStackName;
}
public void setSelectedYarnStackName(String selectedYarnStackName) {
this.selectedYarnStackName = selectedYarnStackName;
}
public boolean isSelectedYarnStackAvailable() {
return selectedYarnStackId != null;
}
public void resetSelectedYarnStackId() {
selectedYarnStackId = null;
}
public void setSelectedYarnStackId(Long selectedYarnStackId) {
this.selectedYarnStackId = selectedYarnStackId;
}
public void resetYarnHostGroups() {
this.yarnHostgroups = new HashMap<>();
}
public Set<String> getConstraints() {
return constraintTemplates;
}
public void setConstraints(Set<ConstraintTemplateResponse> constraintTemplateResponses) {
constraintTemplates = new HashSet<>();
for (ConstraintTemplateResponse constraintTemplateResponse : constraintTemplateResponses) {
constraintTemplates.add(constraintTemplateResponse.getName());
}
}
public Boolean isPlatformSelectionDisabled() {
return cloudbreakClient.accountPreferencesEndpoint().isPlatformSelectionDisabled().get("disabled");
}
public Set<String> getEnabledPlatforms() {
return enabledPlatforms;
}
public boolean isPlatformAvailable(String platform) {
return getEnabledPlatforms() == null || getEnabledPlatforms().contains(platform);
}
public void setEnabledPlatforms(Set<String> enabledPlatforms) {
this.enabledPlatforms = enabledPlatforms;
}
public Map<String, MarathonHostgroupEntry> putMarathonHostGroup(String name, MarathonHostgroupEntry hostgroupEntry) {
this.marathonHostgroups.put(name, hostgroupEntry);
return this.marathonHostgroups;
}
public Map<String, MarathonHostgroupEntry> getMarathonHostGroups() {
return marathonHostgroups;
}
public Map<String, AvailabilitySetEntry> putAzureAvailabilitySet(String name, AvailabilitySetEntry azureAvailabilitySetEntry) {
this.azureAvailabilitySets.put(name, azureAvailabilitySetEntry);
return this.azureAvailabilitySets;
}
public Map<String, AvailabilitySetEntry> getAzureAvailabilitySets() {
return azureAvailabilitySets;
}
public Map<String, YarnHostgroupEntry> putYarnHostGroup(String name, YarnHostgroupEntry hostgroupEntry) {
this.yarnHostgroups.put(name, hostgroupEntry);
return this.yarnHostgroups;
}
public Map<String, YarnHostgroupEntry> getYarnHostGroups() {
return yarnHostgroups;
}
public boolean isCredentialAvailable() {
return isPropertyAvailable(PropertyKey.CREDENTIAL_ID);
}
public void setCredential(String id) {
CredentialResponse credential = cloudbreakClient.credentialEndpoint().get(Long.valueOf(id));
this.activeCloudPlatform = credential.getCloudPlatform();
List<TemplateResponse> templateResponses = new ArrayList<>();
for (TemplateResponse templateResponse : cloudbreakClient.templateEndpoint().getPublics()) {
if (this.activeCloudPlatform.equals(templateResponse.getCloudPlatform())) {
templateResponses.add(templateResponse);
}
}
fillTemplates(templateResponses);
addProperty(PropertyKey.CREDENTIAL_ID, id);
if (credential.getCloudPlatform().equals("BYOS")) {
byosOrchestrator = credential.getParameters().get("type").toString();
byosEndpoint = credential.getParameters().get("apiEndpoint").toString();
} else {
byosOrchestrator = null;
byosEndpoint = null;
}
setCredentialAccessible();
}
public String getApiEndpoint() {
return byosEndpoint;
}
public CredentialResponse getCredentialById(String id) {
return cloudbreakClient.credentialEndpoint().get(Long.valueOf(id));
}
private void fillTemplates(List<TemplateResponse> templateList) {
for (TemplateResponse t : templateList) {
templateMap.put(t.getId(), t);
this.activeTemplateNames.add(t.getName());
this.activeTemplates.add(t.getId().toString());
}
}
public FileSystemType getFileSystemType() {
return fileSystemType;
}
public void setFileSystemType(FileSystemType fileSystemType) {
this.fileSystemType = fileSystemType;
}
public Map<String, Object> getFileSystemParameters() {
return fileSystemParameters;
}
public void setFileSystemParameters(Map<String, Object> fileSystemParameters) {
this.fileSystemParameters = fileSystemParameters;
}
public Boolean getDefaultFileSystem() {
return defaultFileSystem;
}
public void setDefaultFileSystem(Boolean defaultFileSystem) {
this.defaultFileSystem = defaultFileSystem;
}
public void setPlatformToVariantsMap(Map<String, Collection<String>> platformToVariants) {
this.platformToVariants = platformToVariants;
}
public Collection<String> getVariantsByPlatform(String platform) {
return platformToVariants.get(platform);
}
public void setRegions(Map<String, Collection<String>> regions) {
this.regions = regions;
}
public Collection<String> getRegionsByPlatform(String platform) {
return regions.get(platform);
}
public void setAvailabilityZones(Map<String, Map<String, Collection<String>>> availabilityZones) {
this.availabilityZones = availabilityZones;
}
public Collection<String> getAvailabilityZonesByPlatform(String platform) {
Collection<String> result = Lists.newArrayList();
Map<String, Collection<String>> regionZones = availabilityZones.get(platform);
for (Collection<String> zones : regionZones.values()) {
result.addAll(zones);
}
return result;
}
public Collection<String> getAvailabilityZonesByRegion(String platform, String region) {
return availabilityZones.get(platform).get(region);
}
public Map<String, Map<String, Collection<VmTypeJson>>> getVmTypesPerZones() {
return vmTypesPerZones;
}
public void setVmTypesPerZones(Map<String, Map<String, Collection<VmTypeJson>>> vmTypesPerZones) {
this.vmTypesPerZones = vmTypesPerZones;
}
public Map<String, Map<String, String>> getDefaultVmTypePerZones() {
return defaultVmTypePerZones;
}
public void setDefaultVmTypePerZones(Map<String, Map<String, String>> defaultVmTypePerZones) {
this.defaultVmTypePerZones = defaultVmTypePerZones;
}
public Collection<String> getInstanceTypeNamesByPlatform(String platform) {
Collection<String> result = Lists.newArrayList();
Collection<Map<String, String>> platformInstances = instanceTypes.get(platform);
for (Map<String, String> instance : platformInstances) {
result.add(instance.get("value"));
}
return result;
}
public Collection<String> getOrchestratorNamesByPlatform(String platform) {
return orchestrators.get(platform);
}
public Set<String> getActiveHostGroups() {
return activeHostGroups;
}
public Set<String> getActiveInstanceGroups() {
return activeInstanceGroups;
}
public void setBlueprintAccessible() {
addProperty(PropertyKey.BLUEPRINT_ACCESSIBLE, ACCESSIBLE);
}
public boolean isBlueprintAccessible() {
return isPropertyAvailable(PropertyKey.BLUEPRINT_ACCESSIBLE);
}
public boolean isRdsConfigAccessible() {
return isPropertyAvailable(PropertyKey.RDSCONFIG_ACCESSIBLE);
}
public void setCredentialAccessible() {
addProperty(PropertyKey.CREDENTIAL_ACCESSIBLE, ACCESSIBLE);
}
public boolean isCredentialAccessible() {
return isPropertyAvailable(PropertyKey.CREDENTIAL_ACCESSIBLE);
}
public void setStackAccessible() {
addProperty(PropertyKey.STACK_ACCESSIBLE, ACCESSIBLE);
}
public boolean isStackAccessible() {
return isPropertyAvailable(PropertyKey.STACK_ACCESSIBLE);
}
public void setRecipeAccessible() {
addProperty(PropertyKey.RECIPE_ACCESSIBLE, ACCESSIBLE);
}
public boolean isRecipeAccessible() {
return isPropertyAvailable(PropertyKey.RECIPE_ACCESSIBLE);
}
public String getStackId() {
return getLastPropertyValue(PropertyKey.STACK_ID);
}
public String getStackName() {
return getLastPropertyValue(PropertyKey.STACK_NAME);
}
public String getBlueprintId() {
return getLastPropertyValue(PropertyKey.BLUEPRINT_ID);
}
public void removeBlueprintId() {
removeProperty(PropertyKey.BLUEPRINT_ID);
}
public String getRecipeId() {
return getLastPropertyValue(PropertyKey.RECIPE_ID);
}
public String getCredentialId() {
return getLastPropertyValue(PropertyKey.CREDENTIAL_ID);
}
public Map<Long, String> getNetworksByProvider() {
return networksByProvider;
}
public Map<Long, String> getRdsConfigs() {
return rdsConfigs;
}
public boolean isSssdConfigAccessible() {
return isPropertyAvailable(PropertyKey.SSSDCONFIG_ACCESSIBLE);
}
public void setSssdConfigAccessible() {
addProperty(PropertyKey.SSSDCONFIG_ACCESSIBLE, ACCESSIBLE);
}
public void addSssdConfig(String id) {
addProperty(PropertyKey.SSSDCONFIG_ID, id);
setSssdConfigAccessible();
}
public void addRdsConfig(String rdsConfigId) {
addProperty(PropertyKey.RDSCONFIG_ID, rdsConfigId);
setSssdConfigAccessible();
}
public void setRdsConfigAccessible() {
addProperty(PropertyKey.RDSCONFIG_ACCESSIBLE, ACCESSIBLE);
}
public String getSssdConfigId() {
return getLastPropertyValue(PropertyKey.SSSDCONFIG_ID);
}
public String getRdsConfigId() {
return getLastPropertyValue(PropertyKey.RDSCONFIG_ID);
}
public boolean isLdapConfigAccessible() {
return isPropertyAvailable(PropertyKey.LDAPCONFIG_ACCESSIBLE);
}
public void setLdapConfigAccessible() {
addProperty(PropertyKey.LDAPCONFIG_ACCESSIBLE, ACCESSIBLE);
}
public void addLdapConfig(String id) {
addProperty(PropertyKey.LDAPCONFIG_ID, id);
setSssdConfigAccessible();
}
public String getLdapConfigId() {
return getLastPropertyValue(PropertyKey.LDAPCONFIG_ID);
}
public Map<Long, String> getLdapConfigs() {
return ldapConfigs;
}
public void putNetwork(Long id, String provider) {
networksByProvider.put(id, provider);
}
public void putNetworks(Map<Long, String> networksByProvider) {
this.networksByProvider.putAll(networksByProvider);
}
public void putRdsConfig(Long id, String name) {
rdsConfigs.put(id, name);
}
public void putLdapConfig(Long id, String name) {
this.ldapConfigs.put(id, name);
}
public void putSecurityGroup(Long id, String name) {
this.securityGroups.put(id, name);
}
public Map<Long, String> getSecurityGroups() {
return securityGroups;
}
public void setSecurityGroups(Map<Long, String> securityGroups) {
this.securityGroups = securityGroups;
}
public Long getActiveNetworkId() {
return activeNetworkId;
}
public void setActiveNetworkId(Long activeNetworkId) {
this.activeNetworkId = activeNetworkId;
}
/**
* Sets the focus to the root.
*/
public void resetFocus() {
this.focus = getRootFocus();
}
/**
* Sets the focus.
*
* @param id target of the focus
* @param type type of the focus
*/
public void setFocus(String id, FocusType type) {
this.focus = new Focus(id, type);
}
public FocusType getFocusType() {
return focus.getType();
}
/**
* Sets what should be the next hint message.
*
* @param hint the new message
*/
public void setHint(Hints hint) {
this.hint = hint;
}
/**
* Returns the context sensitive prompt.
*
* @return text of the prompt
*/
public String getPrompt() {
return focus.isType(FocusType.ROOT) ? "cloudbreak-shell>" : formatPrompt(focus.getPrefix(), focus.getValue());
}
/**
* Returns some context sensitive hint.
*
* @return hint
*/
public String getHint() {
return "Hint: " + hint.message();
}
private Focus getRootFocus() {
return new Focus("root", FocusType.ROOT);
}
private String formatPrompt(String prefix, String postfix) {
return prefix + (postfix == null ? "" : ":" + postfix) + ">";
}
private boolean isPropertyAvailable(PropertyKey key) {
return properties.get(key) != null && !properties.get(key).isEmpty();
}
public boolean isMarathonMode() {
return "MESOS".equals(byosOrchestrator);
}
public boolean isYarnMode() {
return "YARN".equals(byosOrchestrator);
}
private void addProperty(PropertyKey key, String value) {
properties.remove(key);
properties.put(key, value);
}
private void removeProperty(PropertyKey key) {
properties.remove(key);
}
private String getLastPropertyValue(PropertyKey key) {
try {
return properties.get(key);
} catch (Exception ex) {
return "";
}
}
private String getBlueprintText(String id) {
BlueprintResponse bp = cloudbreakClient.blueprintEndpoint().get(Long.valueOf(id));
return bp.getAmbariBlueprint();
}
public void setVolumeTypes(Map<String, Collection<String>> volumeTypes) {
this.volumeTypes = volumeTypes;
}
public Collection<String> getVolumeTypesByPlatform(String platform) {
return volumeTypes.get(platform);
}
public void setInstanceTypes(Map<String, List<Map<String, String>>> instanceTypes) {
this.instanceTypes = instanceTypes;
}
public void setOrchestrators(Map<String, Collection<String>> orchestrators) {
this.orchestrators = orchestrators;
}
public void setAmbariDatabaseDetailsJson(AmbariDatabaseDetailsJson details) {
this.ambariDatabaseDetailsJson = details;
}
public AmbariDatabaseDetailsJson getAmbariDatabaseDetailsJson() {
return ambariDatabaseDetailsJson;
}
public void resetAmbariDatabaseDetailsJson() {
this.ambariDatabaseDetailsJson = null;
}
private enum PropertyKey {
CREDENTIAL_ID,
BLUEPRINT_ID,
RECIPE_ID,
STACK_ID,
STACK_NAME,
CREDENTIAL_ACCESSIBLE,
BLUEPRINT_ACCESSIBLE,
STACK_ACCESSIBLE,
RECIPE_ACCESSIBLE,
SSSDCONFIG_ACCESSIBLE,
SSSDCONFIG_ID,
RDSCONFIG_ACCESSIBLE,
RDSCONFIG_ID,
RDSCONFIG_NAME,
LDAPCONFIG_ID,
LDAPCONFIG_ACCESSIBLE
}
}