Skip to content

Commit 1b081f7

Browse files
Merge pull request #1766 from edsonarios/issue1320
Added csv output format
2 parents 97cb046 + 0a29669 commit 1b081f7

File tree

4 files changed

+77
-1
lines changed

4 files changed

+77
-1
lines changed

SoftLayer/CLI/core.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
}
3535

3636
PROG_NAME = "slcli (SoftLayer Command-line)"
37-
VALID_FORMATS = ['table', 'raw', 'json', 'jsonraw']
37+
VALID_FORMATS = ['table', 'raw', 'json', 'jsonraw', 'csv']
3838
DEFAULT_FORMAT = 'raw'
3939

4040
if sys.stdout.isatty():

SoftLayer/CLI/formatting.py

+51
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,11 @@
66
"""
77
# pylint: disable=E0202, consider-merging-isinstance, arguments-differ, keyword-arg-before-vararg
88
import collections
9+
import csv
10+
import io
911
import json
1012
import os
13+
import sys
1114

1215
import click
1316
from rich import box
@@ -29,6 +32,8 @@ def format_output(data, fmt='table'): # pylint: disable=R0911,R0912
2932
return json.dumps(data, indent=4, cls=CLIJSONEncoder)
3033
elif fmt == 'jsonraw':
3134
return json.dumps(data, cls=CLIJSONEncoder)
35+
if fmt == 'csv':
36+
return csv_output_format(data)
3237

3338
if isinstance(data, str) or isinstance(data, rTable):
3439
return data
@@ -440,3 +445,49 @@ def _format_list_objects(result):
440445
table.add_row(values)
441446

442447
return table
448+
449+
450+
def csv_output_format(data, delimiter=','):
451+
"""Formating a table to csv format and show it."""
452+
data = clean_table(data, delimiter)
453+
write_csv_format(sys.stdout, data, delimiter)
454+
return ''
455+
456+
457+
def clean_table(data, delimiter):
458+
"""Delete Null fields by '-' and fix nested table in table"""
459+
new_data_row = []
460+
for row in data.rows:
461+
new_value = []
462+
for value in row:
463+
if str(value) == 'NULL':
464+
value = '-'
465+
466+
if str(type(value)) == "<class 'SoftLayer.CLI.formatting.Table'>":
467+
string_io = io.StringIO()
468+
write_csv_format(string_io, value, delimiter)
469+
470+
nested_table_converted = string_io.getvalue()
471+
nested_table_converted = nested_table_converted.replace('\r', '').split('\n')
472+
nested_table_converted.pop()
473+
474+
title_nested_table = new_value.pop()
475+
for item in nested_table_converted:
476+
new_value.append(title_nested_table)
477+
new_value.append(item)
478+
new_data_row.append(new_value)
479+
new_value = []
480+
else:
481+
new_value.append(value)
482+
483+
if len(new_value) != 0:
484+
new_data_row.append(new_value)
485+
data.rows = new_data_row
486+
return data
487+
488+
489+
def write_csv_format(support_output, data, delimiter):
490+
"""Write csv format to supported output"""
491+
writer = csv.writer(support_output, delimiter=delimiter)
492+
writer.writerow(data.columns)
493+
writer.writerows(data.rows)

tests/CLI/modules/account_tests.py

+8
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,14 @@ def test_invoice_detail_details(self):
6666
self.assert_no_fail(result)
6767
self.assert_called_with('SoftLayer_Billing_Invoice', 'getInvoiceTopLevelItems', identifier='1234')
6868

69+
def test_invoice_detail_csv_output_format(self):
70+
result = self.run_command(["--format", "csv", 'account', 'invoice-detail', '1234'])
71+
result_output = result.output.replace('\r', '').split('\n')
72+
self.assert_no_fail(result)
73+
self.assertEqual(result_output[0], 'Item Id,Category,Description,Single,Monthly,Create Date,Location')
74+
self.assertEqual(result_output[1], '724951323,Private (only) Secondary VLAN IP Addresses,64 Portable Private'
75+
' IP Addresses (bleg.beh.com),$0.00,$0.00,2018-04-04,fra02')
76+
6977
# slcli account invoices
7078
def test_invoices(self):
7179
result = self.run_command(['account', 'invoices'])

tests/CLI/modules/vs/vs_tests.py

+17
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,23 @@ def test_detail_vs_ptr_error(self):
313313
output = json.loads(result.output)
314314
self.assertEqual(output.get('ptr', None), None)
315315

316+
def test_vs_detail_csv_output_format_with_nested_tables(self):
317+
result = self.run_command(["--format", "csv", 'vs', 'detail', '100'])
318+
result_output = result.output.replace('\r', '').split('\n')
319+
self.assert_no_fail(result)
320+
self.assertEqual(result_output[0], 'name,value')
321+
self.assertEqual(result_output[1], 'id,100')
322+
self.assertEqual(result_output[16], 'drives,"Type,Name,Drive,Capacity"')
323+
self.assertEqual(result_output[17], 'drives,"System,Disk,0,100 GB"')
324+
self.assertEqual(result_output[18], 'drives,"Swap,Disk,1,2 GB"')
325+
self.assertEqual(result_output[30], 'vlans,"type,number,id"')
326+
self.assertEqual(result_output[31], 'vlans,"PUBLIC,23,1"')
327+
self.assertEqual(result_output[32], 'Bandwidth,"Type,In GB,Out GB,Allotment"')
328+
self.assertEqual(result_output[33], 'Bandwidth,"Public,.448,.52157,250"')
329+
self.assertEqual(result_output[34], 'Bandwidth,"Private,.03842,.01822,N/A"')
330+
self.assertEqual(result_output[35], 'security_groups,"interface,id,name"')
331+
self.assertEqual(result_output[36], 'security_groups,"PRIVATE,128321,allow_all"')
332+
316333
def test_create_options(self):
317334
result = self.run_command(['vs', 'create-options', '--vsi-type', 'TRANSIENT_CLOUD_SERVER'])
318335
self.assert_no_fail(result)

0 commit comments

Comments
 (0)