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 org.springframework.stereotype.Component;
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.MarathonHostgroupEntry;
import com.sequenceiq.cloudbreak.shell.model.ShellContext;
@Component
public class MarathonCommands implements CommandMarker {
public static final String PLATFORM = "MARATHON";
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 MarathonCommands(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 --MARATHON")
public boolean createStackAvailable() {
return shellContext.isPlatformAvailable(BYOS) && shellContext.getActiveHostGroups().size() == shellContext.getMarathonHostGroups().size();
}
@CliAvailabilityIndicator(value = "credential create --MARATHON")
public boolean createCredentialAvailable() {
return shellContext.isPlatformAvailable(BYOS);
}
@CliCommand(value = "credential create --MARATHON", help = "Create a new MARATHON 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 --MARATHON", help = "Create a new MARATHON 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, MarathonHostgroupEntry>> entries = shellContext.getMarathonHostGroups().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, MarathonHostgroupEntry> 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.setSelectedMarathonStackId(stackResponse.getId());
shellContext.setSelectedMarathonStackName(stackResponse.getName());
return String.format("Stack creation started with id: '%s' and name: '%s'", stackResponse.getId(), stackResponse.getName());
}
@CliCommand(value = "marathon constraint create", help = "Create a new marathon constraint")
public String createMarathonTemplate(
@CliOption(key = "name", mandatory = true, help = "Name of the marathon constraint") String name,
@CliOption(key = "cores", mandatory = true, help = "Cpu cores of the marathon constraint (0.1 - 64 core)") Double cpuCores,
@CliOption(key = "memory", mandatory = true, help = "Memory in Mb of the marathon constraint (16mb - 128Gb)") Double memory,
@CliOption(key = "diskSize", mandatory = true, help = "Disk in Gb of the marathon constraint (10Gb - 1000Gb)") Double disk,
@CliOption(key = "description", help = "Description of the marathon 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.MARATHON);
if (publicInAccount) {
id = shellContext.cloudbreakClient().constraintTemplateEndpoint().postPublic(constraintTemplateRequest).getId();
} else {
id = shellContext.cloudbreakClient().constraintTemplateEndpoint().postPrivate(constraintTemplateRequest).getId();
}
return "Marathon template was created with id: " + id;
} catch (Exception ex) {
throw shellContext.exceptionTransformer().transformToRuntimeException(ex);
}
}
@CliCommand(value = "marathon constraint list", help = "Shows the currently available marathon constraints")
public String listMarathonTemplates() {
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 = "marathon constraint delete", help = "Delete the marathon constraint by its id or name")
public Object deleteMarathonTemplate(
@CliOption(key = "id", help = "Id of the marathon template") String id,
@CliOption(key = "name", help = "Name of the marathon template") String name) {
try {
if (id != null) {
shellContext.cloudbreakClient().constraintTemplateEndpoint().delete(Long.valueOf(id));
shellContext.setConstraints(shellContext.cloudbreakClient().constraintTemplateEndpoint().getPublics());
return String.format("Marathon 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("Marathon constraint has been deleted, name: %s", name);
}
throw shellContext.exceptionTransformer().transformToRuntimeException("No constraint specified");
} catch (Exception ex) {
return ex.toString();
}
}
@CliCommand(value = "marathon constraint show", help = "Shows the marathon constraint by its id or name")
public Object showTemplate(
@CliOption(key = "id", help = "Id of the marathon constraint") Long id,
@CliOption(key = "name", help = "Name of the marathon 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 = "marathon hostgroup list", help = "list hostgroups")
public String listHostGroup() {
try {
return shellContext.outputTransformer().render(shellContext.getMarathonHostGroups(), "hostgroup");
} catch (Exception ex) {
throw shellContext.exceptionTransformer().transformToRuntimeException(ex);
}
}
@CliCommand(value = "marathon 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.putMarathonHostGroup(hostgroup.getName(), new MarathonHostgroupEntry(nodecount, constraintTemplateName.getName()));
int marathonHostGroupsConfigured = shellContext.getMarathonHostGroups().size();
int totalHostGroupsToConfigure = shellContext.getActiveHostGroups().size();
if (marathonHostGroupsConfigured == totalHostGroupsToConfigure) {
shellContext.setHint(Hints.MARATHON_CLUSTER);
}
return shellContext.outputTransformer().render(shellContext.getMarathonHostGroups(), "hostgroup");
} else {
throw shellContext.exceptionTransformer().transformToRuntimeException("Constraint was not found");
}
} catch (Exception ex) {
throw shellContext.exceptionTransformer().transformToRuntimeException(ex);
}
}
}