package com.sequenceiq.cloudbreak.shell.commands.base; import java.io.BufferedReader; import java.io.File; import java.io.FileReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.URL; import java.util.Map; import java.util.Set; import org.apache.commons.io.IOUtils; import org.apache.http.MethodNotSupportedException; import org.springframework.shell.core.annotation.CliAvailabilityIndicator; import org.springframework.shell.core.annotation.CliCommand; import org.springframework.shell.core.annotation.CliOption; import com.google.common.collect.Maps; import com.sequenceiq.cloudbreak.api.model.TopologyRequest; import com.sequenceiq.cloudbreak.api.model.TopologyResponse; import com.sequenceiq.cloudbreak.shell.commands.BaseCommands; import com.sequenceiq.cloudbreak.shell.commands.PlatformCommands; import com.sequenceiq.cloudbreak.shell.model.Hints; import com.sequenceiq.cloudbreak.shell.model.OutPutType; import com.sequenceiq.cloudbreak.shell.model.ShellContext; public class BasePlatformCommands implements BaseCommands, PlatformCommands { private static final String CREATE_SUCCESS_MSG = "Platform created with id: '%d' and name: '%s'"; private ShellContext shellContext; public BasePlatformCommands(ShellContext shellContext) { this.shellContext = shellContext; } @CliAvailabilityIndicator(value = "platform list") public boolean listAvailable() { return !shellContext.isMarathonMode() && !shellContext.isYarnMode(); } @CliCommand(value = "platform list", help = "Shows the currently available platforms") public String list() { try { Set<TopologyResponse> publics = shellContext.cloudbreakClient().topologyEndpoint().getPublics(); Map<String, String> map = shellContext.responseTransformer().transformToMap(publics, "id", "name"); return shellContext.outputTransformer().render(map, "ID", "INFO"); } catch (Exception e) { throw shellContext.exceptionTransformer().transformToRuntimeException(e); } } @CliAvailabilityIndicator(value = "platform show") public boolean showAvailable() { return !shellContext.isMarathonMode() && !shellContext.isYarnMode(); } @Override public String show(Long id, String name, OutPutType outPutType) { try { outPutType = outPutType == null ? OutPutType.RAW : outPutType; if (id != null) { TopologyResponse topologyResponse = shellContext.cloudbreakClient().topologyEndpoint().get(id); return shellContext.outputTransformer() .render(outPutType, shellContext.responseTransformer().transformObjectToStringMap(topologyResponse), "FIELD", "VALUE"); } else if (name != null) { TopologyResponse topologyResponse = selectByName(shellContext.cloudbreakClient().topologyEndpoint().getPublics(), name); if (topologyResponse != null) { return shellContext.outputTransformer() .render(outPutType, shellContext.responseTransformer().transformObjectToStringMap(topologyResponse), "FIELD", "VALUE"); } } throw shellContext.exceptionTransformer().transformToRuntimeException("No platform specified"); } catch (Exception e) { throw shellContext.exceptionTransformer().transformToRuntimeException(e); } } @CliCommand(value = "platform show --id", help = "Show the platform by its id") @Override public String showById( @CliOption(key = "", mandatory = true) Long id, @CliOption(key = "outputType", help = "OutputType of the response") OutPutType outPutType) throws Exception { return show(id, null, outPutType); } @CliCommand(value = "platform show --name", help = "Show the platform by its name") @Override public String showByName( @CliOption(key = "", mandatory = true) String name, @CliOption(key = "outputType", help = "OutputType of the response") OutPutType outPutType) throws Exception { return show(null, name, outPutType); } @Override public boolean selectAvailable() { return false; } @Override public String select(Long id, String name) throws Exception { throw new MethodNotSupportedException("Platform select command not available."); } @Override public String selectById(Long id) throws Exception { return select(id, null); } @Override public String selectByName(String name) throws Exception { return select(null, name); } @CliAvailabilityIndicator(value = "platform delete") @Override public boolean deleteAvailable() { return !shellContext.isMarathonMode() && !shellContext.isYarnMode(); } @Override public String delete(Long id, String name) { try { if (id != null) { shellContext.cloudbreakClient().topologyEndpoint().delete(id, false); return String.format("Platform has been deleted, id: %s", id); } else if (name != null) { Long idForName = getIdForName(shellContext.cloudbreakClient().topologyEndpoint().getPublics(), name); if (idForName != null) { shellContext.cloudbreakClient().topologyEndpoint().delete(idForName, false); return String.format("Platform has been deleted, name: %s", name); } } throw shellContext.exceptionTransformer().transformToRuntimeException("No platform specified"); } catch (Exception e) { throw shellContext.exceptionTransformer().transformToRuntimeException(e); } } @CliCommand(value = "platform delete --id", help = "Delete the platform by its id") @Override public String deleteById(@CliOption(key = "", mandatory = true) Long id) throws Exception { return delete(id, null); } @CliCommand(value = "platform delete --name", help = "Delete the platform by its name") @Override public String deleteByName(@CliOption(key = "", mandatory = true) String name) throws Exception { return delete(null, name); } @Override public boolean createPlatformAvailable(String platform) { return true; } public String create(String name, String description, String cloudPlatform, Map<String, String> mapping) { try { TopologyRequest req = new TopologyRequest(); req.setCloudPlatform(cloudPlatform); req.setName(name); req.setDescription(description); req.setNodes(mapping); Long id = shellContext.cloudbreakClient().topologyEndpoint().postPublic(req).getId(); shellContext.setHint(Hints.CREATE_CREDENTIAL_WITH_TOPOLOGY); return String.format(CREATE_SUCCESS_MSG, id, name); } catch (Exception e) { throw shellContext.exceptionTransformer().transformToRuntimeException(e); } } @Override public Map<String, String> convertMappingFile(File file, String url) { Map<String, String> result = Maps.newHashMap(); if (file != null || url != null) { BufferedReader bf = null; try { bf = getReader(file, url); String line; while ((line = bf.readLine()) != null) { String[] mapping = line.split("\\s+"); if (mapping.length != 2) { continue; } result.put(mapping[0], mapping[1]); } } catch (IOException e) { throw shellContext.exceptionTransformer().transformToRuntimeException(e); } finally { IOUtils.closeQuietly(bf); } } return result; } @Override public ShellContext shellContext() { return shellContext; } private BufferedReader getReader(File file, String url) { try { if (file != null) { return IOUtils.toBufferedReader(new FileReader(file)); } return IOUtils.toBufferedReader(new InputStreamReader((new URL(url)).openStream())); } catch (IOException e) { throw shellContext.exceptionTransformer().transformToRuntimeException(e); } } private Long getIdForName(Set<TopologyResponse> publics, String name) { TopologyResponse t = selectByName(publics, name); if (t != null) { return t.getId(); } return null; } private TopologyResponse selectByName(Set<TopologyResponse> publics, String name) { if (publics != null) { for (TopologyResponse res : publics) { if (res.getName().equals(name)) { return res; } } } return null; } }