package com.sequenceiq.cloudbreak.shell.commands.base; import static com.sequenceiq.cloudbreak.shell.util.TopologyUtil.checkTopologyForResource; 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.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.CredentialRequest; import com.sequenceiq.cloudbreak.api.model.CredentialResponse; import com.sequenceiq.cloudbreak.shell.commands.BaseCommands; import com.sequenceiq.cloudbreak.shell.commands.CredentialCommands; import com.sequenceiq.cloudbreak.shell.model.Hints; import com.sequenceiq.cloudbreak.shell.model.OutPutType; import com.sequenceiq.cloudbreak.shell.model.ShellContext; public class BaseCredentialCommands implements BaseCommands, CredentialCommands { private static final String FILE_NOT_FOUND = "File not found with ssh key"; private static final String URL_NOT_FOUND = "Url not Available for ssh key"; private static final String CREATE_SUCCESS_MESSAGE = "Credential created with id: '%d' and name: '%s'"; private ShellContext shellContext; public BaseCredentialCommands(ShellContext shellContext) { this.shellContext = shellContext; } @Override @CliAvailabilityIndicator(value = { "credential delete --id", "credential delete --name" }) public boolean deleteAvailable() { return true; } @CliCommand(value = "credential delete --id", help = "Delete the credential by its id") @Override public String deleteById(@CliOption(key = "", mandatory = true) Long id) throws Exception { return delete(id, null); } @CliCommand(value = "credential delete --name", help = "Delete the credential by its name") @Override public String deleteByName(@CliOption(key = "", mandatory = true) String name) throws Exception { return delete(null, name); } @Override public String delete(Long id, String name) { try { if (id != null) { shellContext.cloudbreakClient().credentialEndpoint().delete(id); return String.format("Credential deleted, id: %s", id); } else if (name != null) { shellContext.cloudbreakClient().credentialEndpoint().deletePublic(name); return String.format("Credential deleted, name: %s", name); } throw shellContext.exceptionTransformer().transformToRuntimeException("No credential specified (select a credential by --id or --name)"); } catch (Exception ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(ex); } } @Override @CliAvailabilityIndicator(value = { "credential select --id", "credential select --name" }) public boolean selectAvailable() { return shellContext.isCredentialAccessible(); } @CliCommand(value = "credential select --id", help = "Select the credential by its id") @Override public String selectById(@CliOption(key = "", mandatory = true) Long id) throws Exception { return select(id, null); } @CliCommand(value = "credential select --name", help = "Select the credential by its name") @Override public String selectByName(@CliOption(key = "", mandatory = true) String name) throws Exception { return select(null, name); } @Override public String select(Long id, String name) { try { if (id != null) { if (shellContext.cloudbreakClient().credentialEndpoint().get(id) != null) { shellContext.setCredential(id.toString()); createOrSelectTemplateHint(); return "Credential selected, id: " + id; } } else if (name != null) { CredentialResponse aPublic = shellContext.cloudbreakClient().credentialEndpoint().getPublic(name); shellContext.setCredential(aPublic.getId().toString()); createOrSelectTemplateHint(); return "Credential selected, name: " + name; } throw shellContext.exceptionTransformer().transformToRuntimeException("No credential specified (select a credential by --id or --name)"); } catch (Exception ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(ex); } } @Override @CliAvailabilityIndicator(value = "credential list") public boolean listAvailable() { return true; } @Override @CliCommand(value = "credential list", help = "Shows all of your credentials") public String list() { try { Set<CredentialResponse> publics = shellContext.cloudbreakClient().credentialEndpoint().getPublics(); return shellContext.outputTransformer().render(shellContext.responseTransformer().transformToMap(publics, "id", "name"), "ID", "INFO"); } catch (Exception ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(ex); } } @Override @CliAvailabilityIndicator(value = { "credential show --id", "credential show --name" }) public boolean showAvailable() { return true; } @CliCommand(value = "credential show --id", help = "Show the credential 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 = "credential show --name", help = "Show the credential 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 String show(Long id, String name, OutPutType outPutType) { try { outPutType = outPutType == null ? OutPutType.RAW : outPutType; if (id != null) { CredentialResponse credentialResponse = shellContext.cloudbreakClient().credentialEndpoint().get(id); Map<String, String> map = shellContext.responseTransformer().transformObjectToStringMap(credentialResponse); return shellContext.outputTransformer().render(outPutType, map, "FIELD", "VALUE"); } else if (name != null) { CredentialResponse aPublic = shellContext.cloudbreakClient().credentialEndpoint().getPublic(name); if (aPublic != null) { return shellContext.outputTransformer().render(outPutType, shellContext.responseTransformer().transformObjectToStringMap(aPublic), "FIELD", "VALUE"); } } throw shellContext.exceptionTransformer().transformToRuntimeException("No credential specified (select a credential by --id or --name)"); } catch (Exception ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(ex); } } @Override public boolean createCredentialAvailable(String platform) { return true; } @Override public String create(String name, File sshKeyPath, String sshKeyUrl, String sshKeyString, String description, boolean publicInAccount, Long platformId, Map<String, Object> parameters, String platform) { if ((sshKeyPath == null) && (sshKeyUrl == null || sshKeyUrl.isEmpty()) && sshKeyString == null) { throw shellContext.exceptionTransformer().transformToRuntimeException( "An SSH public key must be specified either with --sshKeyPath or --sshKeyUrl or --sshKeyString"); } String sshKey; if (sshKeyPath != null) { try { sshKey = IOUtils.toString(new FileReader(new File(sshKeyPath.getPath()))); } catch (IOException ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(FILE_NOT_FOUND); } } else if (sshKeyUrl != null) { try { sshKey = readUrl(sshKeyUrl); } catch (IOException ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(URL_NOT_FOUND); } } else { sshKey = sshKeyString; } try { CredentialRequest credentialRequest = new CredentialRequest(); credentialRequest.setName(name); credentialRequest.setDescription(description); credentialRequest.setCloudPlatform(platform); credentialRequest.setPublicKey(sshKey); credentialRequest.setParameters(parameters); if (platformId != null) { checkTopologyForResource(shellContext.cloudbreakClient().topologyEndpoint().getPublics(), platformId, platform); } credentialRequest.setTopologyId(platformId); Long id; if (publicInAccount) { id = shellContext.cloudbreakClient().credentialEndpoint().postPublic(credentialRequest).getId(); } else { id = shellContext.cloudbreakClient().credentialEndpoint().postPrivate(credentialRequest).getId(); } shellContext.setCredential(id.toString()); createOrSelectTemplateHint(); return String.format(CREATE_SUCCESS_MESSAGE, id, name); } catch (Exception ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(ex); } } @Override public ShellContext shellContext() { return shellContext; } protected void createOrSelectTemplateHint() { if (shellContext.cloudbreakClient().credentialEndpoint().getPublics().isEmpty()) { shellContext.setHint(Hints.ADD_BLUEPRINT); } else { shellContext.setHint(Hints.SELECT_BLUEPRINT); } } protected String readUrl(String url) throws IOException { if (!url.startsWith("http://") && !url.startsWith("https://")) { url = "http://" + url; } BufferedReader in = new BufferedReader(new InputStreamReader(new URL(url).openStream())); String str; StringBuilder sb = new StringBuilder(); while ((str = in.readLine()) != null) { sb.append(str); } in.close(); return sb.toString(); } }