package com.sequenceiq.cloudbreak.shell.commands.base; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set; 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.SecurityGroupRequest; import com.sequenceiq.cloudbreak.api.model.SecurityGroupResponse; import com.sequenceiq.cloudbreak.api.model.SecurityRuleRequest; import com.sequenceiq.cloudbreak.shell.commands.BaseCommands; import com.sequenceiq.cloudbreak.shell.commands.SecurityGroupCommands; import com.sequenceiq.cloudbreak.shell.completion.SecurityRules; import com.sequenceiq.cloudbreak.shell.model.Hints; import com.sequenceiq.cloudbreak.shell.model.OutPutType; import com.sequenceiq.cloudbreak.shell.model.ShellContext; public class BaseSecurityGroupCommands implements BaseCommands, SecurityGroupCommands { private static final String CREATE_SUCCESS_MSG = "Security group created and selected successfully, with id: '%d' and name: '%s'"; private ShellContext shellContext; public BaseSecurityGroupCommands(ShellContext shellContext) { this.shellContext = shellContext; } @Override public boolean createSecurityGroupAvailable(String platform) { return !shellContext.isMarathonMode() && !shellContext.isYarnMode(); } @Override public String create(String name, String description, String existingSecurityGroupId, String platform, SecurityRules rules, Boolean publicInAccount) { try { Map<String, String> tcpRules = new HashMap<>(); Map<String, String> udpRules = new HashMap<>(); for (Map<String, String> rule : rules.getRules()) { if ("tcp".equals(rule.get("protocol"))) { tcpRules.put(rule.get("subnet"), rule.get("ports")); } else { udpRules.put(rule.get("subnet"), rule.get("ports")); } } Long id; SecurityGroupRequest securityGroupRequest = new SecurityGroupRequest(); securityGroupRequest.setName(name); securityGroupRequest.setDescription(description); securityGroupRequest.setCloudPlatform(platform); List<SecurityRuleRequest> securityRuleRequestList = new ArrayList<>(); if (existingSecurityGroupId != null && !existingSecurityGroupId.isEmpty()) { securityGroupRequest.setSecurityGroupId(existingSecurityGroupId); } for (Map.Entry<String, String> stringStringEntry : tcpRules.entrySet()) { SecurityRuleRequest securityRuleRequest = new SecurityRuleRequest(); securityRuleRequest.setPorts(stringStringEntry.getValue()); securityRuleRequest.setSubnet(stringStringEntry.getKey()); securityRuleRequest.setProtocol("tcp"); securityRuleRequestList.add(securityRuleRequest); } for (Map.Entry<String, String> stringStringEntry : udpRules.entrySet()) { SecurityRuleRequest securityRuleRequest = new SecurityRuleRequest(); securityRuleRequest.setPorts(stringStringEntry.getValue()); securityRuleRequest.setSubnet(stringStringEntry.getKey()); securityRuleRequest.setProtocol("udp"); securityRuleRequestList.add(securityRuleRequest); } securityGroupRequest.setSecurityRules(securityRuleRequestList); if (publicInAccount) { id = shellContext.cloudbreakClient().securityGroupEndpoint().postPublic(securityGroupRequest).getId(); } else { id = shellContext.cloudbreakClient().securityGroupEndpoint().postPrivate(securityGroupRequest).getId(); } shellContext.putSecurityGroup(id, name); setHint(); return String.format(CREATE_SUCCESS_MSG, id, name); } catch (Exception ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(ex); } } @CliAvailabilityIndicator(value = { "securitygroup delete --id", "securitygroup delete --name" }) @Override public boolean deleteAvailable() { return !shellContext.getSecurityGroups().isEmpty() && !shellContext.isMarathonMode() && !shellContext.isYarnMode(); } @Override public String delete(Long securityGroupId, String securityGroupName) { try { Long id = securityGroupId == null ? null : securityGroupId; String name = securityGroupName == null ? null : securityGroupName; if (id != null) { shellContext.cloudbreakClient().securityGroupEndpoint().delete(id); refreshSecurityGroupsInContext(); return String.format("SecurityGroup deleted with %s id", name); } else if (name != null) { shellContext.cloudbreakClient().securityGroupEndpoint().deletePublic(name); refreshSecurityGroupsInContext(); return String.format("SecurityGroup deleted with %s name", name); } throw shellContext.exceptionTransformer().transformToRuntimeException("No security group specified"); } catch (Exception ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(ex); } } @CliCommand(value = "securitygroup delete --id", help = "Delete the securitygroup by its id") @Override public String deleteById(@CliOption(key = "", mandatory = true) Long id) throws Exception { return delete(id, null); } @CliCommand(value = "securitygroup delete --name", help = "Delete the securitygroup by its name") @Override public String deleteByName(@CliOption(key = "", mandatory = true) String name) throws Exception { return delete(null, name); } @Override public boolean selectAvailable() { return false; } @Override public String select(Long secId, String secName) throws UnsupportedOperationException { throw new UnsupportedOperationException("Select is not supported on securitygroups"); } @CliCommand(value = "securitygroup select --id", help = "Select the securitygroup by its id") @Override public String selectById(@CliOption(key = "", mandatory = true) Long id) throws Exception { return select(id, null); } @CliCommand(value = "securitygroup select --name", help = "Select the securitygroup by its name") @Override public String selectByName(@CliOption(key = "", mandatory = true) String name) throws Exception { return select(null, name); } @CliAvailabilityIndicator(value = "securitygroup list") @Override public boolean listAvailable() { return !shellContext.isMarathonMode() && !shellContext.isYarnMode(); } @CliCommand(value = "securitygroup list", help = "Shows the currently available security groups") public String list() { try { Set<SecurityGroupResponse> publics = shellContext.cloudbreakClient().securityGroupEndpoint().getPublics(); Map<Long, String> updatedGroups = new HashMap<>(); for (SecurityGroupResponse aPublic : publics) { updatedGroups.put(aPublic.getId(), aPublic.getName()); } shellContext.setSecurityGroups(updatedGroups); return shellContext.outputTransformer().render(updatedGroups, "ID", "NAME"); } catch (Exception ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(ex); } } @CliAvailabilityIndicator(value = { "securitygroup show --id", "securitygroup show --name" }) @Override public boolean showAvailable() { return !shellContext.getSecurityGroups().isEmpty() && !shellContext.isMarathonMode() && !shellContext.isYarnMode(); } @Override public String show(Long groupId, String groupName, OutPutType outPutType) { try { outPutType = outPutType == null ? OutPutType.RAW : outPutType; Long id = groupId == null ? null : groupId; String name = groupName == null ? null : groupName; if (id != null) { SecurityGroupResponse securityGroupResponse = shellContext.cloudbreakClient().securityGroupEndpoint().get(id); return shellContext.outputTransformer().render(outPutType, shellContext.responseTransformer().transformObjectToStringMap(securityGroupResponse), "FIELD", "VALUE"); } else if (name != null) { SecurityGroupResponse aPublic = shellContext.cloudbreakClient().securityGroupEndpoint().getPublic(name); return shellContext.outputTransformer().render(outPutType, shellContext.responseTransformer().transformObjectToStringMap(aPublic), "FIELD", "VALUE"); } throw shellContext.exceptionTransformer().transformToRuntimeException("Security group could not be found"); } catch (Exception ex) { throw shellContext.exceptionTransformer().transformToRuntimeException(ex); } } @CliCommand(value = "securitygroup show --id", help = "Show the securitygroup 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 = "securitygroup show --name", help = "Show the securitygroup 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 ShellContext shellContext() { return shellContext; } private void refreshSecurityGroupsInContext() { shellContext.getSecurityGroups().clear(); Set<SecurityGroupResponse> publics = shellContext.cloudbreakClient().securityGroupEndpoint().getPublics(); for (SecurityGroupResponse securityGroup : publics) { shellContext.putSecurityGroup(securityGroup.getId(), securityGroup.getName()); } } private void setHint() { shellContext.setHint(Hints.CREATE_STACK); } }