Skip to content

Commit f4f403c

Browse files
Merge pull request #1251 from caberos/issue1242
implement the new feature hw billing and vs billing
2 parents 273bea5 + 16ad4e0 commit f4f403c

File tree

7 files changed

+157
-36
lines changed

7 files changed

+157
-36
lines changed

SoftLayer/CLI/hardware/billing.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""Get billing for a hardware device."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
6+
import SoftLayer
7+
from SoftLayer.CLI import environment
8+
from SoftLayer.CLI import formatting
9+
from SoftLayer.CLI import helpers
10+
from SoftLayer import utils
11+
12+
13+
@click.command()
14+
@click.argument('identifier')
15+
@environment.pass_env
16+
def cli(env, identifier):
17+
"""Get billing for a hardware device."""
18+
hardware = SoftLayer.HardwareManager(env.client)
19+
20+
hardware_id = helpers.resolve_id(hardware.resolve_ids, identifier, 'hardware')
21+
result = hardware.get_hardware(hardware_id)
22+
table = formatting.KeyValueTable(['name', 'value'])
23+
table.align['name'] = 'r'
24+
table.align['value'] = 'l'
25+
26+
table.add_row(['Id', identifier])
27+
28+
table.add_row(['Billing Item Id', utils.lookup(result, 'billingItem', 'id')])
29+
table.add_row(['Recurring Fee', utils.lookup(result, 'billingItem', 'recurringFee')])
30+
table.add_row(['Total', utils.lookup(result, 'billingItem', 'nextInvoiceTotalRecurringAmount')])
31+
table.add_row(['Provision Date', utils.lookup(result, 'billingItem', 'provisionDate')])
32+
33+
price_table = formatting.Table(['Item', 'Recurring Price'])
34+
for item in utils.lookup(result, 'billingItem', 'children') or []:
35+
price_table.add_row([item['description'], item['nextInvoiceTotalRecurringAmount']])
36+
37+
table.add_row(['prices', price_table])
38+
env.fout(table)

SoftLayer/CLI/routes.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323

2424
('virtual', 'SoftLayer.CLI.virt'),
2525
('virtual:bandwidth', 'SoftLayer.CLI.virt.bandwidth:cli'),
26+
('virtual:billing', 'SoftLayer.CLI.virt.billing:cli'),
2627
('virtual:cancel', 'SoftLayer.CLI.virt.cancel:cli'),
2728
('virtual:capture', 'SoftLayer.CLI.virt.capture:cli'),
2829
('virtual:create', 'SoftLayer.CLI.virt.create:cli'),
@@ -232,6 +233,7 @@
232233
('hardware:create', 'SoftLayer.CLI.hardware.create:cli'),
233234
('hardware:create-options', 'SoftLayer.CLI.hardware.create_options:cli'),
234235
('hardware:detail', 'SoftLayer.CLI.hardware.detail:cli'),
236+
('hardware:billing', 'SoftLayer.CLI.hardware.billing:cli'),
235237
('hardware:edit', 'SoftLayer.CLI.hardware.edit:cli'),
236238
('hardware:list', 'SoftLayer.CLI.hardware.list:cli'),
237239
('hardware:power-cycle', 'SoftLayer.CLI.hardware.power:power_cycle'),

SoftLayer/CLI/virt/billing.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
"""Get billing for a virtual device."""
2+
# :license: MIT, see LICENSE for more details.
3+
4+
import click
5+
6+
import SoftLayer
7+
from SoftLayer.CLI import environment
8+
from SoftLayer.CLI import formatting
9+
from SoftLayer.CLI import helpers
10+
from SoftLayer import utils
11+
12+
13+
@click.command()
14+
@click.argument('identifier')
15+
@environment.pass_env
16+
def cli(env, identifier):
17+
"""Get billing for a virtual device."""
18+
virtual = SoftLayer.VSManager(env.client)
19+
20+
virtual_id = helpers.resolve_id(virtual.resolve_ids, identifier, 'virtual')
21+
result = virtual.get_instance(virtual_id)
22+
table = formatting.KeyValueTable(['name', 'value'])
23+
table.align['name'] = 'r'
24+
table.align['value'] = 'l'
25+
26+
table.add_row(['Id', identifier])
27+
28+
table.add_row(['Billing Item Id', utils.lookup(result, 'billingItem', 'id')])
29+
table.add_row(['Recurring Fee', utils.lookup(result, 'billingItem', 'recurringFee')])
30+
table.add_row(['Total', utils.lookup(result, 'billingItem', 'nextInvoiceTotalRecurringAmount')])
31+
table.add_row(['Provision Date', utils.lookup(result, 'billingItem', 'provisionDate')])
32+
33+
price_table = formatting.Table(['Recurring Price'])
34+
for item in utils.lookup(result, 'billingItem', 'children') or []:
35+
price_table.add_row([item['nextInvoiceTotalRecurringAmount']])
36+
37+
table.add_row(['prices', price_table])
38+
env.fout(table)

docs/cli/hardware.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,10 @@ Provides some basic functionality to order a server. `slcli order` has a more fu
3636
:prog: hardware detail
3737
:show-nested:
3838

39+
.. click:: SoftLayer.CLI.hardware.billing:cli
40+
:prog: hw billing
41+
:show-nested:
42+
3943

4044
.. click:: SoftLayer.CLI.hardware.edit:cli
4145
:prog: hardware edit

docs/cli/vs.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ If no timezone is specified, IMS local time (CST) will be assumed, which might n
245245
:prog: virtual usage
246246
:show-nested:
247247

248+
.. click:: SoftLayer.CLI.virt.billing:cli
249+
:prog: vs billing
250+
:show-nested:
251+
248252

249253
.. click:: SoftLayer.CLI.virt.detail:cli
250254
:prog: virtual detail

tests/CLI/modules/server_tests.py

Lines changed: 34 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -659,19 +659,19 @@ def test_dns_sync_both(self, confirm_mock):
659659
'getResourceRecords')
660660
getResourceRecords.return_value = []
661661
createAargs = ({
662-
'type': 'a',
663-
'host': 'hardware-test1',
664-
'domainId': 12345, # from SoftLayer_Account::getDomains
665-
'data': '172.16.1.100',
666-
'ttl': 7200
667-
},)
662+
'type': 'a',
663+
'host': 'hardware-test1',
664+
'domainId': 12345, # from SoftLayer_Account::getDomains
665+
'data': '172.16.1.100',
666+
'ttl': 7200
667+
},)
668668
createPTRargs = ({
669-
'type': 'ptr',
670-
'host': '100',
671-
'domainId': 123456,
672-
'data': 'hardware-test1.test.sftlyr.ws',
673-
'ttl': 7200
674-
},)
669+
'type': 'ptr',
670+
'host': '100',
671+
'domainId': 123456,
672+
'data': 'hardware-test1.test.sftlyr.ws',
673+
'ttl': 7200
674+
},)
675675

676676
result = self.run_command(['hw', 'dns-sync', '1000'])
677677

@@ -714,12 +714,12 @@ def test_dns_sync_v6(self, confirm_mock):
714714
}
715715
}
716716
createV6args = ({
717-
'type': 'aaaa',
718-
'host': 'hardware-test1',
719-
'domainId': 12345, # from SoftLayer_Account::getDomains
720-
'data': '2607:f0d0:1b01:0023:0000:0000:0000:0004',
721-
'ttl': 7200
722-
},)
717+
'type': 'aaaa',
718+
'host': 'hardware-test1',
719+
'domainId': 12345, # from SoftLayer_Account::getDomains
720+
'data': '2607:f0d0:1b01:0023:0000:0000:0000:0004',
721+
'ttl': 7200
722+
},)
723723
server.return_value = test_server
724724
result = self.run_command(['hw', 'dns-sync', '--aaaa-record', '1000'])
725725
self.assert_no_fail(result)
@@ -826,3 +826,19 @@ def test_dns_sync_misc_exception(self, confirm_mock):
826826
result = self.run_command(['hw', 'dns-sync', '-a', '1000'])
827827
self.assertEqual(result.exit_code, 2)
828828
self.assertIsInstance(result.exception, exceptions.CLIAbort)
829+
830+
def test_billing(self):
831+
result = self.run_command(['hw', 'billing', '123456'])
832+
billing_json = {
833+
'Billing Item Id': 6327,
834+
'Id': '123456',
835+
'Provision Date': None,
836+
'Recurring Fee': 1.54,
837+
'Total': 16.08,
838+
'prices': [{
839+
'Item': 'test',
840+
'Recurring Price': 1
841+
}]
842+
}
843+
self.assert_no_fail(result)
844+
self.assertEqual(json.loads(result.output), billing_json)

tests/CLI/modules/vs/vs_tests.py

Lines changed: 37 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -320,19 +320,19 @@ def test_dns_sync_both(self, confirm_mock):
320320
'getResourceRecords')
321321
getResourceRecords.return_value = []
322322
createAargs = ({
323-
'type': 'a',
324-
'host': 'vs-test1',
325-
'domainId': 12345, # from SoftLayer_Account::getDomains
326-
'data': '172.16.240.2',
327-
'ttl': 7200
328-
},)
323+
'type': 'a',
324+
'host': 'vs-test1',
325+
'domainId': 12345, # from SoftLayer_Account::getDomains
326+
'data': '172.16.240.2',
327+
'ttl': 7200
328+
},)
329329
createPTRargs = ({
330-
'type': 'ptr',
331-
'host': '2',
332-
'domainId': 123456,
333-
'data': 'vs-test1.test.sftlyr.ws',
334-
'ttl': 7200
335-
},)
330+
'type': 'ptr',
331+
'host': '2',
332+
'domainId': 123456,
333+
'data': 'vs-test1.test.sftlyr.ws',
334+
'ttl': 7200
335+
},)
336336

337337
result = self.run_command(['vs', 'dns-sync', '100'])
338338

@@ -375,12 +375,12 @@ def test_dns_sync_v6(self, confirm_mock):
375375
}
376376
}
377377
createV6args = ({
378-
'type': 'aaaa',
379-
'host': 'vs-test1',
380-
'domainId': 12345,
381-
'data': '2607:f0d0:1b01:0023:0000:0000:0000:0004',
382-
'ttl': 7200
383-
},)
378+
'type': 'aaaa',
379+
'host': 'vs-test1',
380+
'domainId': 12345,
381+
'data': '2607:f0d0:1b01:0023:0000:0000:0000:0004',
382+
'ttl': 7200
383+
},)
384384
guest.return_value = test_guest
385385
result = self.run_command(['vs', 'dns-sync', '--aaaa-record', '100'])
386386
self.assert_no_fail(result)
@@ -740,3 +740,22 @@ def test_bandwidth_vs_quite(self):
740740
self.assertEqual(output_summary[1]['Max Date'], date)
741741
self.assertEqual(output_summary[2]['Max GB'], 0.1172)
742742
self.assertEqual(output_summary[3]['Sum GB'], 0.0009)
743+
744+
def test_billing(self):
745+
result = self.run_command(['vs', 'billing', '123456'])
746+
vir_billing = {
747+
'Billing Item Id': 6327,
748+
'Id': '123456',
749+
'Provision Date': None,
750+
'Recurring Fee': None,
751+
'Total': 1.54,
752+
'prices': [
753+
{'Recurring Price': 1},
754+
{'Recurring Price': 1},
755+
{'Recurring Price': 1},
756+
{'Recurring Price': 1},
757+
{'Recurring Price': 1}
758+
]
759+
}
760+
self.assert_no_fail(result)
761+
self.assertEqual(json.loads(result.output), vir_billing)

0 commit comments

Comments
 (0)