Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions SoftLayer/CLI/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,23 @@
('hardware:credentials', 'SoftLayer.CLI.hardware.credentials:cli'),
('hardware:update-firmware', 'SoftLayer.CLI.hardware.update_firmware:cli'),

('securitygroup', 'SoftLayer.CLI.securitygroup'),
('securitygroup:list', 'SoftLayer.CLI.securitygroup.list:cli'),
('securitygroup:detail', 'SoftLayer.CLI.securitygroup.detail:cli'),
('securitygroup:create', 'SoftLayer.CLI.securitygroup.create:cli'),
('securitygroup:edit', 'SoftLayer.CLI.securitygroup.edit:cli'),
('securitygroup:delete', 'SoftLayer.CLI.securitygroup.delete:cli'),
('securitygroup:rule-list', 'SoftLayer.CLI.securitygroup.rule:rule_list'),
('securitygroup:rule-add', 'SoftLayer.CLI.securitygroup.rule:add'),
('securitygroup:rule-edit', 'SoftLayer.CLI.securitygroup.rule:edit'),
('securitygroup:rule-remove', 'SoftLayer.CLI.securitygroup.rule:remove'),
('securitygroup:interface-list',
'SoftLayer.CLI.securitygroup.interface:interface_list'),
('securitygroup:interface-add',
'SoftLayer.CLI.securitygroup.interface:add'),
('securitygroup:interface-remove',
'SoftLayer.CLI.securitygroup.interface:remove'),

('sshkey', 'SoftLayer.CLI.sshkey'),
('sshkey:add', 'SoftLayer.CLI.sshkey.add:cli'),
('sshkey:remove', 'SoftLayer.CLI.sshkey.remove:cli'),
Expand Down Expand Up @@ -256,6 +273,7 @@
'lb': 'loadbal',
'meta': 'metadata',
'my': 'metadata',
'sg': 'securitygroup',
'server': 'hardware',
'vm': 'virtual',
'vs': 'virtual',
Expand Down
1 change: 1 addition & 0 deletions SoftLayer/CLI/securitygroup/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Network security groups."""
32 changes: 32 additions & 0 deletions SoftLayer/CLI/securitygroup/create.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
"""Create security groups."""
# :license: MIT, see LICENSE for more details.

import click

import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting


@click.command()
@click.option('--name', '-n',
help="The name of the security group")
@click.option('--description', '-d',
help="The description of the security group")
@environment.pass_env
def cli(env, name, description):
"""Create a security group."""
mgr = SoftLayer.NetworkManager(env.client)

result = mgr.create_securitygroup(name, description)
table = formatting.KeyValueTable(['name', 'value'])
table.align['name'] = 'r'
table.align['value'] = 'l'
table.add_row(['id', result['id']])
table.add_row(['name',
result.get('name') or formatting.blank()])
table.add_row(['description',
result.get('description') or formatting.blank()])
table.add_row(['created', result['createDate']])

env.fout(table)
17 changes: 17 additions & 0 deletions SoftLayer/CLI/securitygroup/delete.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
"""Delete a security group."""
# :license: MIT, see LICENSE for more details.

import click
import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import exceptions


@click.command()
@click.argument('securitygroup_id')
@environment.pass_env
def cli(env, securitygroup_id):
"""Deletes the given security group"""
mgr = SoftLayer.NetworkManager(env.client)
if not mgr.delete_securitygroup(securitygroup_id):
raise exceptions.CLIAbort("Failed to delete security group")
73 changes: 73 additions & 0 deletions SoftLayer/CLI/securitygroup/detail.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
"""Get details about a security group."""
# :license: MIT, see LICENSE for more details.

import click

import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting


@click.command()
@click.argument('identifier')
@environment.pass_env
def cli(env, identifier):
"""Get details about a security group."""

mgr = SoftLayer.NetworkManager(env.client)

secgroup = mgr.get_securitygroup(identifier)

table = formatting.KeyValueTable(['name', 'value'])
table.align['name'] = 'r'
table.align['value'] = 'l'

table.add_row(['id', secgroup['id']])
table.add_row(['name', secgroup.get('name') or formatting.blank()])
table.add_row(['description',
secgroup.get('description') or formatting.blank()])

rule_table = formatting.Table(['id', 'remoteIp', 'remoteGroupId',
'direction', 'ethertype', 'portRangeMin',
'portRangeMax', 'protocol'])
for rule in secgroup.get('rules', []):
rg_id = rule.get('remoteGroup', {}).get('id') or formatting.blank()
port_min = rule.get('portRangeMin')
port_max = rule.get('portRangeMax')
if port_min is None:
port_min = formatting.blank()
if port_max is None:
port_max = formatting.blank()
rule_table.add_row([rule['id'],
rule.get('remoteIp') or formatting.blank(),
rule.get('remoteGroupId', rg_id),
rule['direction'],
rule.get('ethertype') or formatting.blank(),
port_min,
port_max,
rule.get('protocol') or formatting.blank()])

table.add_row(['rules', rule_table])

vsi_table = formatting.Table(['id', 'hostname', 'interface', 'ipAddress'])

for binding in secgroup.get('networkComponentBindings', []):
try:
vsi = binding['networkComponent']['guest']
vsi_id = vsi['id']
hostname = vsi['hostname']
interface = ('PRIVATE' if binding['networkComponent']['port'] == 0
else 'PUBLIC')
ip_address = (vsi['primaryBackendIpAddress']
if binding['networkComponent']['port'] == 0
else vsi['primaryIpAddress'])
except KeyError:
vsi_id = "N/A"
hostname = "Not enough permission to view"
interface = "N/A"
ip_address = "N/A"
vsi_table.add_row([vsi_id, hostname, interface, ip_address])

table.add_row(['servers', vsi_table])

env.fout(table)
28 changes: 28 additions & 0 deletions SoftLayer/CLI/securitygroup/edit.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
"""Edit details of a security group."""
# :license: MIT, see LICENSE for more details.

import click

import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import exceptions


@click.command()
@click.argument('group_id')
@click.option('--name', '-n',
help="The name of the security group")
@click.option('--description', '-d',
help="The description of the security group")
@environment.pass_env
def cli(env, group_id, name, description):
"""Edit details of a security group."""
mgr = SoftLayer.NetworkManager(env.client)
data = {}
if name:
data['name'] = name
if description:
data['description'] = description

if not mgr.edit_securitygroup(group_id, **data):
raise exceptions.CLIAbort("Failed to edit security group")
150 changes: 150 additions & 0 deletions SoftLayer/CLI/securitygroup/interface.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
"""Security group interface operations."""
# :license: MIT, see LICENSE for more details.

import click

import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import exceptions
from SoftLayer.CLI import formatting

COLUMNS = ['networkComponentId',
'virtualServerId',
'hostname',
'interface',
'ipAddress', ]


@click.command()
@click.argument('securitygroup_id')
@click.option('--sortby',
help='Column to sort by',
type=click.Choice(COLUMNS))
@environment.pass_env
def interface_list(env, securitygroup_id, sortby):
"""List interfaces associated with security groups."""
mgr = SoftLayer.NetworkManager(env.client)

table = formatting.Table(COLUMNS)
table.sortby = sortby

mask = (
'''networkComponentBindings[
networkComponentId,
networkComponent[
id,
port,
guest[
id,
hostname,
primaryBackendIpAddress,
primaryIpAddress
]
]
]'''
)

secgroup = mgr.get_securitygroup(securitygroup_id, mask=mask)
for binding in secgroup.get('networkComponentBindings', []):
interface_id = binding['networkComponentId']
try:
interface = binding['networkComponent']
vsi = interface['guest']
vsi_id = vsi['id']
hostname = vsi['hostname']
priv_pub = 'PRIVATE' if interface['port'] == 0 else 'PUBLIC'
ip_address = (vsi['primaryBackendIpAddress']
if interface['port'] == 0
else vsi['primaryIpAddress'])
except KeyError:
vsi_id = "N/A"
hostname = "Not enough permission to view"
priv_pub = "N/A"
ip_address = "N/A"

table.add_row([
interface_id,
vsi_id,
hostname,
priv_pub,
ip_address
])

env.fout(table)


@click.command()
@click.argument('securitygroup_id')
@click.option('--network-component', '-n',
help=('The network component to associate '
'with the security group'))
@click.option('--server', '-s',
help='The server ID to associate with the security group')
@click.option('--interface', '-i',
help='The interface of the server to associate (public/private)')
@environment.pass_env
def add(env, securitygroup_id, network_component, server, interface):
"""Attach an interface to a security group."""
_validate_args(network_component, server, interface)

mgr = SoftLayer.NetworkManager(env.client)
component_id = _get_component_id(env, network_component, server, interface)

success = mgr.attach_securitygroup_component(securitygroup_id,
component_id)
if not success:
raise exceptions.CLIAbort("Could not attach network component")


@click.command()
@click.argument('securitygroup_id')
@click.option('--network-component', '-n',
help=('The network component to remove from '
'with the security group'))
@click.option('--server', '-s',
help='The server ID to remove from the security group')
@click.option('--interface', '-i',
help='The interface of the server to remove (public/private)')
@environment.pass_env
def remove(env, securitygroup_id, network_component, server, interface):
"""Detach an interface from a security group."""
_validate_args(network_component, server, interface)

mgr = SoftLayer.NetworkManager(env.client)
component_id = _get_component_id(env, network_component, server, interface)

success = mgr.detach_securitygroup_component(securitygroup_id,
component_id)
if not success:
raise exceptions.CLIAbort("Could not detach network component")


def _validate_args(network_component, server, interface):
use_server = bool(server and interface and not network_component)
use_component = bool(network_component and not bool(server or interface))

if not use_server and not use_component:
raise exceptions.CLIAbort("Must set either --network-component "
"or both --server and --interface")
if use_server and interface.lower() not in ['public', 'private']:
raise exceptions.CLIAbort(
"Interface must be either 'public' or 'private'")


def _get_component_id(env, network_component, server, interface):
use_server = bool(server and interface and not network_component)
vs_mgr = SoftLayer.VSManager(env.client)

if use_server:
vs_mask = 'networkComponents[id, port]'
vsi = vs_mgr.get_instance(server, mask=vs_mask)
port = 0 if interface.lower() == 'private' else 1
component = [c for c in vsi['networkComponents'] if c['port'] == port]
if len(component) != 1:
raise exceptions.CLIAbort("Instance %s has no %s interface"
% (server, interface))
component_id = component[0]['id']
else:
component_id = network_component

return component_id
36 changes: 36 additions & 0 deletions SoftLayer/CLI/securitygroup/list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""List securitygroups."""
# :license: MIT, see LICENSE for more details.

import click

import SoftLayer
from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting

COLUMNS = ['id',
'name',
'description', ]


@click.command()
@click.option('--sortby',
help='Column to sort by',
type=click.Choice(COLUMNS))
@environment.pass_env
def cli(env, sortby):
"""List security groups."""

mgr = SoftLayer.NetworkManager(env.client)

table = formatting.Table(COLUMNS)
table.sortby = sortby

sgs = mgr.list_securitygroups()
for secgroup in sgs:
table.add_row([
secgroup['id'],
secgroup.get('name') or formatting.blank(),
secgroup.get('description') or formatting.blank(),
])

env.fout(table)
Loading