Skip to content
Merged

Tags #1281

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
2 changes: 2 additions & 0 deletions SoftLayer/CLI/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
PROG_NAME = "slcli (SoftLayer Command-line)"
VALID_FORMATS = ['table', 'raw', 'json', 'jsonraw']
DEFAULT_FORMAT = 'raw'

if sys.stdout.isatty():
DEFAULT_FORMAT = 'table'

Expand Down Expand Up @@ -157,6 +158,7 @@ def cli(env,

logger.setLevel(DEBUG_LOGGING_MAP.get(verbose, logging.DEBUG))
env.vars['_timings'] = SoftLayer.DebugTransport(env.client.transport)
env.vars['verbose'] = verbose
env.client.transport = env.vars['_timings']


Expand Down
8 changes: 8 additions & 0 deletions SoftLayer/CLI/routes.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,14 @@
('subnet:list', 'SoftLayer.CLI.subnet.list:cli'),
('subnet:lookup', 'SoftLayer.CLI.subnet.lookup:cli'),

('tags', 'SoftLayer.CLI.tags'),
('tags:cleanup', 'SoftLayer.CLI.tags.cleanup:cli'),
('tags:list', 'SoftLayer.CLI.tags.list:cli'),
('tags:set', 'SoftLayer.CLI.tags.set:cli'),
('tags:details', 'SoftLayer.CLI.tags.details:cli'),
('tags:delete', 'SoftLayer.CLI.tags.delete:cli'),
('tags:taggable', 'SoftLayer.CLI.tags.taggable:cli'),

('ticket', 'SoftLayer.CLI.ticket'),
('ticket:create', 'SoftLayer.CLI.ticket.create:cli'),
('ticket:detail', 'SoftLayer.CLI.ticket.detail:cli'),
Expand Down
1 change: 1 addition & 0 deletions SoftLayer/CLI/tags/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
"""Manage Tags"""
26 changes: 26 additions & 0 deletions SoftLayer/CLI/tags/cleanup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""Removes unused Tags"""
# :license: MIT, see LICENSE for more details.

import click

from SoftLayer.CLI import environment
from SoftLayer.managers.tags import TagManager


@click.command()
@click.option('--dry-run', '-d', is_flag=True, default=False,
help="Don't delete, just show what will be deleted.")
@environment.pass_env
def cli(env, dry_run):
"""Removes all empty tags."""

tag_manager = TagManager(env.client)
empty_tags = tag_manager.get_unattached_tags()

for tag in empty_tags:
if dry_run:
click.secho("(Dry Run) Removing {}".format(tag.get('name')), fg='yellow')
else:
result = tag_manager.delete_tag(tag.get('name'))
color = 'green' if result else 'red'
click.secho("Removing {}".format(tag.get('name')), fg=color)
29 changes: 29 additions & 0 deletions SoftLayer/CLI/tags/delete.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Delete Tags."""
# :license: MIT, see LICENSE for more details.

import click

from SoftLayer.CLI import environment
from SoftLayer.managers.tags import TagManager


@click.command()
@click.argument('identifier')
@click.option('--name', required=False, default=False, is_flag=True, show_default=False,
help='Assume identifier is a tag name. Useful if your tag name is a number.')
@environment.pass_env
def cli(env, identifier, name):
"""Delete a Tag. Tag names that contain spaces need to be encased in quotes"""

tag_manager = TagManager(env.client)
tag_name = identifier
# If the identifier is a int, and user didn't tell us it was a name.
if str.isdigit(identifier) and not name:
tag = tag_manager.get_tag(identifier)
tag_name = tag.get('name', None)

result = tag_manager.delete_tag(tag_name)
if result:
click.secho("Tag {} has been removed".format(tag_name), fg='green')
else:
click.secho("Failed to remove tag {}".format(tag_name), fg='red')
27 changes: 27 additions & 0 deletions SoftLayer/CLI/tags/details.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Details of a Tag."""
# :license: MIT, see LICENSE for more details.

import click

from SoftLayer.CLI import environment
from SoftLayer.CLI.tags.list import detailed_table
from SoftLayer.managers.tags import TagManager


@click.command()
@click.argument('identifier')
@click.option('--name', required=False, default=False, is_flag=True, show_default=False,
help='Assume identifier is a tag name. Useful if your tag name is a number.')
@environment.pass_env
def cli(env, identifier, name):
"""Get details for a Tag. Identifier can be either a name or tag-id"""

tag_manager = TagManager(env.client)

# If the identifier is a int, and user didn't tell us it was a name.
if str.isdigit(identifier) and not name:
tags = [tag_manager.get_tag(identifier)]
else:
tags = tag_manager.get_tag_by_name(identifier)
table = detailed_table(tag_manager, tags)
env.fout(table)
75 changes: 75 additions & 0 deletions SoftLayer/CLI/tags/list.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
"""List Tags."""
# :license: MIT, see LICENSE for more details.

import click

from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer.exceptions import SoftLayerAPIError
from SoftLayer.managers.tags import TagManager
from SoftLayer import utils

# pylint: disable=unnecessary-lambda


@click.command()
@click.option('--detail', '-d', is_flag=True, default=False,
help="Show information about the resources using this tag.")
@environment.pass_env
def cli(env, detail):
"""List Tags."""

tag_manager = TagManager(env.client)

if detail:
tables = detailed_table(tag_manager, tag_manager.get_attached_tags())
for table in tables:
env.fout(table)
else:
table = simple_table(tag_manager)
env.fout(table)
# pp(tags.list_tags())


def tag_row(tag):
"""Format a tag table row"""
return [tag.get('id'), tag.get('name'), tag.get('referenceCount', 0)]


def detailed_table(tag_manager, tags):
"""Creates a table for each tag, with details about resources using it"""
tables = []
for tag in tags:
references = tag_manager.get_tag_references(tag.get('id'))
# pp(references)
new_table = formatting.Table(['Id', 'Type', 'Resource'], title=tag.get('name'))
for reference in references:
tag_type = utils.lookup(reference, 'tagType', 'keyName')
resource_id = reference.get('resourceTableId')
resource_row = get_resource_name(tag_manager, resource_id, tag_type)
new_table.add_row([resource_id, tag_type, resource_row])
tables.append(new_table)

return tables


def simple_table(tag_manager):
"""Just tags and how many resources on each"""
tags = tag_manager.list_tags()
table = formatting.Table(['Id', 'Tag', 'Count'], title='Tags')
for tag in tags.get('attached', []):
table.add_row(tag_row(tag))
for tag in tags.get('unattached', []):
table.add_row(tag_row(tag))
return table


def get_resource_name(tag_manager, resource_id, tag_type):
"""Returns a string to identify a resource"""
name = None
try:
resource = tag_manager.reference_lookup(resource_id, tag_type)
name = tag_manager.get_resource_name(resource, tag_type)
except SoftLayerAPIError as exception:
name = "{}".format(exception.reason)
return name
26 changes: 26 additions & 0 deletions SoftLayer/CLI/tags/set.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
"""Set Tags."""
# :license: MIT, see LICENSE for more details.

import click

from SoftLayer.CLI import environment
from SoftLayer.managers.tags import TagManager


@click.command()
@click.option('--tags', '-t', type=click.STRING, required=True,
help='Comma seperated list of tags, enclosed in quotes. "tag1, tag2"')
@click.option('--key-name', '-k', type=click.STRING, required=True,
help="Key name of a tag type e.g. GUEST, HARDWARE. See slcli tags taggable output.")
@click.option('--resource-id', '-r', type=click.INT, required=True, help="ID of the object being tagged")
@environment.pass_env
def cli(env, tags, key_name, resource_id):
"""Set Tags."""

tag_manager = TagManager(env.client)
tags = tag_manager.set_tags(tags, key_name, resource_id)

if tags:
click.secho("Set tags successfully", fg='green')
else:
click.secho("Failed to set tags", fg='red')
27 changes: 27 additions & 0 deletions SoftLayer/CLI/tags/taggable.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""List everything that could be tagged."""
# :license: MIT, see LICENSE for more details.

import click

from SoftLayer.CLI import environment
from SoftLayer.CLI import formatting
from SoftLayer.managers.tags import TagManager


@click.command()
@environment.pass_env
def cli(env):
"""List everything that could be tagged."""

tag_manager = TagManager(env.client)
tag_types = tag_manager.get_all_tag_types()
for tag_type in tag_types:
title = "{} ({})".format(tag_type['description'], tag_type['keyName'])
table = formatting.Table(['Id', 'Name'], title=title)
resources = tag_manager.taggable_by_type(tag_type['keyName'])
for resource in resources:
table.add_row([
resource['resource']['id'],
tag_manager.get_resource_name(resource['resource'], tag_type['keyName'])
])
env.fout(table)
59 changes: 59 additions & 0 deletions SoftLayer/fixtures/SoftLayer_Hardware.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
getObject = {
'id': 1234,
'globalIdentifier': 'xxxxc-asd',
'datacenter': {'id': 12, 'name': 'DALLAS21',
'description': 'Dallas 21'},
'billingItem': {
'id': 6327,
'recurringFee': 1.54,
'nextInvoiceTotalRecurringAmount': 16.08,
'children': [
{'description': 'test', 'nextInvoiceTotalRecurringAmount': 1},
],
'orderItem': {
'order': {
'userRecord': {
'username': 'bob',
}
}
}
},
'primaryIpAddress': '4.4.4.4',
'hostname': 'testtest1',
'domain': 'test.sftlyr.ws',
'bareMetalInstanceFlag': True,
'fullyQualifiedDomainName': 'testtest1.test.sftlyr.ws',
'processorPhysicalCoreAmount': 4,
'memoryCapacity': 4,
'primaryBackendIpAddress': '10.4.4.4',
'networkManagementIpAddress': '10.4.4.4',
'hardwareStatus': {'status': 'ACTIVE'},
'primaryNetworkComponent': {'maxSpeed': 1000, 'speed': 1000},
'provisionDate': '2020-08-01 15:23:45',
'notes': 'NOTES NOTES NOTES',
'operatingSystem': {
'softwareLicense': {
'softwareDescription': {
'referenceCode': 'UBUNTU_20_64',
'name': 'Ubuntu',
'version': 'Ubuntu 20.04 LTS',
}
},
'passwords': [
{'username': 'root', 'password': 'xxxxxxxxxxxx'}
],
},
'remoteManagementAccounts': [
{'username': 'root', 'password': 'zzzzzzzzzzzzzz'}
],
'networkVlans': [
{
'networkSpace': 'PRIVATE',
'vlanNumber': 1234,
'id': 11111
},
],
'tagReferences': [
{'tag': {'name': 'a tag'}}
],
}
32 changes: 16 additions & 16 deletions SoftLayer/fixtures/SoftLayer_Network_Storage_Allowed_Host.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,22 +32,22 @@
getObject = TEST_ALLOWED_HOST

getSubnetsInAcl = [{
'id': 12345678,
'accountId': 1234,
'networkIdentifier': '10.11.12.13',
'cidr': '14',
'billingRecordId': None,
'parentId': None,
'networkVlanId': None,
'createDate': '2020-01-02 00:00:01',
'modifyDate': None,
'subnetType': 'SECONDARY_ON_VLAN',
'restrictAllocationFlag': 0,
'leafFlag': 1,
'ownerId': 1,
'ipAddressBegin': 129123,
'ipAddressEnd': 129145,
'purgeFlag': 0
'id': 12345678,
'accountId': 1234,
'networkIdentifier': '10.11.12.13',
'cidr': '14',
'billingRecordId': None,
'parentId': None,
'networkVlanId': None,
'createDate': '2020-01-02 00:00:01',
'modifyDate': None,
'subnetType': 'SECONDARY_ON_VLAN',
'restrictAllocationFlag': 0,
'leafFlag': 1,
'ownerId': 1,
'ipAddressBegin': 129123,
'ipAddressEnd': 129145,
'purgeFlag': 0
}]

assignSubnetsToAcl = [
Expand Down
23 changes: 23 additions & 0 deletions SoftLayer/fixtures/SoftLayer_Search.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
advancedSearch = [
{
"relevanceScore": "4",
"resourceType": "SoftLayer_Hardware",
"resource": {
"accountId": 307608,
"domain": "vmware.test.com",
"fullyQualifiedDomainName": "host14.vmware.test.com",
"hardwareStatusId": 5,
"hostname": "host14",
"id": 123456,
"manufacturerSerialNumber": "AAAAAAAAA",
"notes": "A test notes",
"provisionDate": "2018-08-24T12:32:10-06:00",
"serialNumber": "SL12345678",
"serviceProviderId": 1,
"hardwareStatus": {
"id": 5,
"status": "ACTIVE"
}
}
}
]
Loading