package com.sequenceiq.cloudbreak.shell.commands.provider;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import org.springframework.shell.core.CommandMarker;
import org.springframework.shell.core.annotation.CliAvailabilityIndicator;
import org.springframework.shell.core.annotation.CliCommand;
import org.springframework.shell.core.annotation.CliOption;
import com.sequenceiq.cloudbreak.api.model.ConstraintTemplateRequest;
import com.sequenceiq.cloudbreak.api.model.ConstraintTemplateResponse;
import com.sequenceiq.cloudbreak.api.model.InstanceGroupRequest;
import com.sequenceiq.cloudbreak.api.model.InstanceGroupType;
import com.sequenceiq.cloudbreak.api.model.OrchestratorRequest;
import com.sequenceiq.cloudbreak.api.model.StackRequest;
import com.sequenceiq.cloudbreak.api.model.StackResponse;
import com.sequenceiq.cloudbreak.common.type.OrchestratorConstants;
import com.sequenceiq.cloudbreak.shell.commands.CredentialCommands;
import com.sequenceiq.cloudbreak.shell.commands.NetworkCommands;
import com.sequenceiq.cloudbreak.shell.commands.PlatformCommands;
import com.sequenceiq.cloudbreak.shell.commands.SecurityGroupCommands;
import com.sequenceiq.cloudbreak.shell.commands.StackCommands;
import com.sequenceiq.cloudbreak.shell.commands.TemplateCommands;
import com.sequenceiq.cloudbreak.shell.completion.ConstraintName;
import com.sequenceiq.cloudbreak.shell.completion.HostGroup;
import com.sequenceiq.cloudbreak.shell.model.Hints;
import com.sequenceiq.cloudbreak.shell.model.ShellContext;
import com.sequenceiq.cloudbreak.shell.model.YarnHostgroupEntry;
public class YarnCommands implements CommandMarker {
public static final String PLATFORM = "YARN";
public static final String BYOS = "BYOS";
private ShellContext shellContext;
private CredentialCommands baseCredentialCommands;
private NetworkCommands baseNetworkCommands;
private SecurityGroupCommands baseSecurityGroupCommands;
private TemplateCommands baseTemplateCommands;
private PlatformCommands basePlatformCommands;
private StackCommands stackCommands;
public YarnCommands(ShellContext shellContext,
CredentialCommands baseCredentialCommands,
NetworkCommands baseNetworkCommands,
SecurityGroupCommands baseSecurityGroupCommands,
TemplateCommands baseTemplateCommands,
PlatformCommands basePlatformCommands,
StackCommands stackCommands) {
this.baseCredentialCommands = baseCredentialCommands;
this.baseNetworkCommands = baseNetworkCommands;
this.baseSecurityGroupCommands = baseSecurityGroupCommands;
this.shellContext = shellContext;
this.baseTemplateCommands = baseTemplateCommands;
this.basePlatformCommands = basePlatformCommands;
this.stackCommands = stackCommands;
}
@CliAvailabilityIndicator(value = "stack create --YARN")
public boolean createStackAvailable() {
return shellContext.isPlatformAvailable(BYOS) && shellContext.getActiveHostGroups().size() == shellContext.getYarnHostGroups().size();
}
@CliAvailabilityIndicator(value = "credential create --YARN")
public boolean createCredentialAvailable() {
return shellContext.isPlatformAvailable(BYOS);
}
@CliCommand(value = "credential create --YARN", help = "Create a new YARN credential")
public String createCredential(
@CliOption(key = "name", mandatory = true, help = "Name of the credential") String name,
@CliOption(key = "publicInAccount", help = "flags if the credential is public in the account",
unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") boolean publicInAccount,
@CliOption(key = "description", help = "Description of the credential") String description,
@CliOption(key = "apiEndpoint", help = "ApiEndpoint of the credential") String apiEndpoint
) {
Map<String, Object> parameters = new HashMap<>();
parameters.put("type", PLATFORM);
parameters.put("apiEndpoint", apiEndpoint);
return baseCredentialCommands.create(name, null, null, null, description, publicInAccount, null, parameters, BYOS);
}
@CliCommand(value = "stack create --YARN", help = "Create a new YARN stack")
public String create(
@CliOption(key = "name", mandatory = true, help = "Name of the stack") String name,
@CliOption(key = "publicInAccount", help = "flags if the stack is public in the account",
unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") boolean publicInAccount,
@CliOption(key = "wait", help = "Wait for stack creation", unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") boolean wait,
@CliOption(key = "timeout", help = "Wait timeout if wait=true", mandatory = false) Long timeout) {
Set<Map.Entry<String, YarnHostgroupEntry>> entries = shellContext.getYarnHostGroups().entrySet();
StackRequest stackRequest = new StackRequest();
OrchestratorRequest orchestratorRequest = new OrchestratorRequest();
orchestratorRequest.setApiEndpoint(shellContext.getApiEndpoint());
orchestratorRequest.setType(PLATFORM);
stackRequest.setName(name);
stackRequest.setOrchestrator(orchestratorRequest);
stackRequest.setRegion("LOCAL");
stackRequest.setCloudPlatform(BYOS);
stackRequest.setCredentialId(Long.valueOf(shellContext.getCredentialId()));
for (Map.Entry<String, YarnHostgroupEntry> entry : entries) {
InstanceGroupRequest instanceGroupRequest = new InstanceGroupRequest();
instanceGroupRequest.setGroup(entry.getKey());
instanceGroupRequest.setType(InstanceGroupType.CORE);
instanceGroupRequest.setNodeCount(entry.getValue().getNodeCount());
stackRequest.getInstanceGroups().add(instanceGroupRequest);
}
StackResponse stackResponse = stackCommands.create(stackRequest, publicInAccount, wait, timeout);
shellContext.setSelectedYarnStackId(stackResponse.getId());
shellContext.setSelectedYarnStackName(stackResponse.getName());
return String.format("Stack creation started with id: '%s' and name: '%s'", stackResponse.getId(), stackResponse.getName());
}
@CliCommand(value = "yarn constraint create", help = "Create a new yarn constraint")
public String createYarnTemplate(
@CliOption(key = "name", mandatory = true, help = "Name of the yarn constraint") String name,
@CliOption(key = "cores", mandatory = true, help = "Cpu cores of the yarn constraint (0.1 - 64 core)") Double cpuCores,
@CliOption(key = "memory", mandatory = true, help = "Memory in Mb of the yarn constraint (16mb - 128Gb)") Double memory,
@CliOption(key = "diskSize", mandatory = true, help = "Disk in Gb of the yarn constraint (10Gb - 1000Gb)") Double disk,
@CliOption(key = "description", help = "Description of the yarn stack") String description,
@CliOption(key = "publicInAccount", help = "flags if the constraint is public in the account",
unspecifiedDefaultValue = "false", specifiedDefaultValue = "true") boolean publicInAccount) {
Long id;
try {
ConstraintTemplateRequest constraintTemplateRequest = new ConstraintTemplateRequest();
constraintTemplateRequest.setName(name);
constraintTemplateRequest.setCpu(cpuCores);
constraintTemplateRequest.setDescription(description);
constraintTemplateRequest.setDisk(disk);
constraintTemplateRequest.setMemory(memory);
constraintTemplateRequest.setOrchestratorType(OrchestratorConstants.YARN);
if (publicInAccount) {
id = shellContext.cloudbreakClient().constraintTemplateEndpoint().postPublic(constraintTemplateRequest).getId();
} else {
id = shellContext.cloudbreakClient().constraintTemplateEndpoint().postPrivate(constraintTemplateRequest).getId();
}
return "Yarn template was created with id: " + id;
} catch (Exception ex) {
throw shellContext.exceptionTransformer().transformToRuntimeException(ex);
}
}
@CliCommand(value = "yarn constraint list", help = "Shows the currently available yarn constraints")
public String listYarnTemplates() {
try {
Set<ConstraintTemplateResponse> publics = shellContext.cloudbreakClient().constraintTemplateEndpoint().getPublics();
shellContext.setConstraints(publics);
return shellContext.outputTransformer().render(shellContext.responseTransformer().transformToMap(publics, "id", "name"), "ID", "INFO");
} catch (Exception ex) {
throw shellContext.exceptionTransformer().transformToRuntimeException(ex);
}
}
@CliCommand(value = "yarn constraint delete", help = "Delete the yarn constraint by its id or name")
public Object deleteYarnTemplate(
@CliOption(key = "id", help = "Id of the yarn template") String id,
@CliOption(key = "name", help = "Name of the yarn template") String name) {
try {
if (id != null) {
shellContext.cloudbreakClient().constraintTemplateEndpoint().delete(Long.valueOf(id));
shellContext.setConstraints(shellContext.cloudbreakClient().constraintTemplateEndpoint().getPublics());
return String.format("Yarn constraint has been deleted, id: %s", id);
} else if (name != null) {
shellContext.cloudbreakClient().constraintTemplateEndpoint().deletePublic(name);
shellContext.setConstraints(shellContext.cloudbreakClient().constraintTemplateEndpoint().getPublics());
return String.format("Yarn constraint has been deleted, name: %s", name);
}
throw shellContext.exceptionTransformer().transformToRuntimeException("No constraint specified");
} catch (Exception ex) {
return ex.toString();
}
}
@CliCommand(value = "yarn constraint show", help = "Shows the yarn constraint by its id or name")
public Object showTemplate(
@CliOption(key = "id", help = "Id of the yarn constraint") Long id,
@CliOption(key = "name", help = "Name of the yarn constraint") String name) {
try {
ConstraintTemplateResponse aPublic = getConstraintTemplateResponse(id, name);
if (aPublic != null) {
return shellContext.outputTransformer().render(shellContext.responseTransformer().transformObjectToStringMap(aPublic), "FIELD", "VALUE");
}
throw shellContext.exceptionTransformer().transformToRuntimeException("No constraint was found");
} catch (Exception ex) {
throw shellContext.exceptionTransformer().transformToRuntimeException(ex);
}
}
private ConstraintTemplateResponse getConstraintTemplateResponse(Long id, String name) {
if (id != null) {
return shellContext.cloudbreakClient().constraintTemplateEndpoint().get(id);
} else {
return shellContext.cloudbreakClient().constraintTemplateEndpoint().getPublic(name);
}
}
@CliCommand(value = "yarn hostgroup list", help = "list hostgroups")
public String listHostGroup() {
try {
return shellContext.outputTransformer().render(shellContext.getYarnHostGroups(), "hostgroup");
} catch (Exception ex) {
throw shellContext.exceptionTransformer().transformToRuntimeException(ex);
}
}
@CliCommand(value = "yarn hostgroup configure", help = "configure hostgroups")
public String createHostGroup(
@CliOption(key = "hostgroup", mandatory = true, help = "Name of the hostgroup") HostGroup hostgroup,
@CliOption(key = "nodecount", mandatory = true, help = "Count of the nodes in the hostgroup") Integer nodecount,
@CliOption(key = "constraintName", mandatory = true, help = "Name of the constraint") ConstraintName constraintTemplateName) {
try {
ConstraintTemplateResponse constraintTemplateResponse = getConstraintTemplateResponse(null, constraintTemplateName.getName());
if (constraintTemplateResponse != null) {
shellContext.putYarnHostGroup(hostgroup.getName(), new YarnHostgroupEntry(nodecount, constraintTemplateName.getName()));
int yarnHostGroupsConfigured = shellContext.getYarnHostGroups().size();
int totalHostGroupsToConfigure = shellContext.getActiveHostGroups().size();
if (yarnHostGroupsConfigured == totalHostGroupsToConfigure) {
shellContext.setHint(Hints.YARN_CLUSTER);
}
return shellContext.outputTransformer().render(shellContext.getYarnHostGroups(), "hostgroup");
} else {
throw shellContext.exceptionTransformer().transformToRuntimeException("Constraint was not found");
}
} catch (Exception ex) {
throw shellContext.exceptionTransformer().transformToRuntimeException(ex);
}
}
}