Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
aws
GitHub Repository: aws/aws-cli
Path: blob/develop/tests/unit/output/test_table_formatter.py
1567 views
1
# Copyright 2012-2013 Amazon.com, Inc. or its affiliates. All Rights Reserved.
2
#
3
# Licensed under the Apache License, Version 2.0 (the "License"). You
4
# may not use this file except in compliance with the License. A copy of
5
# the License is located at
6
#
7
# http://aws.amazon.com/apache2.0/
8
#
9
# or in the "license" file accompanying this file. This file is
10
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
11
# ANY KIND, either express or implied. See the License for the specific
12
# language governing permissions and limitations under the License.
13
import unittest
14
15
from awscli.formatter import TableFormatter
16
from awscli.table import MultiTable, Styler
17
from awscli.compat import StringIO
18
19
SIMPLE_LIST = {
20
"QueueUrls": [
21
"https://us-west-2.queue.amazonaws.com/1/queue1",
22
"https://us-west-2.queue.amazonaws.com/1/queue2",
23
"https://us-west-2.queue.amazonaws.com/1/queue3",
24
"https://us-west-2.queue.amazonaws.com/1/queue4"
25
]
26
}
27
28
29
30
SIMPLE_LIST_TABLE = """\
31
------------------------------------------------------
32
| OperationName |
33
+----------------------------------------------------+
34
|| QueueUrls ||
35
|+--------------------------------------------------+|
36
|| https://us-west-2.queue.amazonaws.com/1/queue1 ||
37
|| https://us-west-2.queue.amazonaws.com/1/queue2 ||
38
|| https://us-west-2.queue.amazonaws.com/1/queue3 ||
39
|| https://us-west-2.queue.amazonaws.com/1/queue4 ||
40
|+--------------------------------------------------+|
41
"""
42
43
SIMPLE_DICT = {"Attributes":
44
{"a": "0",
45
"b": "345600",
46
"c": "0",
47
"d": "65536",
48
"e": "1351044153",
49
"f": "0"}
50
}
51
52
53
SIMPLE_DICT_TABLE = """\
54
----------------------------------------------------
55
| OperationName |
56
+--------------------------------------------------+
57
|| Attributes ||
58
|+---+---------+----+--------+--------------+-----+|
59
|| a | b | c | d | e | f ||
60
|+---+---------+----+--------+--------------+-----+|
61
|| 0| 345600 | 0 | 65536 | 1351044153 | 0 ||
62
|+---+---------+----+--------+--------------+-----+|
63
"""
64
65
66
LIST_OF_DICTS = {
67
"OrderableDBInstanceOptions": [
68
{
69
"AvailabilityZones": [
70
{
71
"Name": "us-east-1a",
72
"ProvisionedIopsCapable": False
73
},
74
{
75
"Name": "us-east-1d",
76
"ProvisionedIopsCapable": True
77
}
78
],
79
"DBInstanceClass": "db.m1.large",
80
"Engine": "mysql",
81
"EngineVersion": "5.1.45",
82
"LicenseModel": "general-public-license",
83
"MultiAZCapable": True,
84
"ReadReplicaCapable": True,
85
"Vpc": False
86
},
87
{
88
"AvailabilityZones": [
89
{
90
"Name": "us-west-2a",
91
"ProvisionedIopsCapable": True
92
},
93
{
94
"Name": "us-west-2b",
95
"ProvisionedIopsCapable": True
96
}
97
],
98
"DBInstanceClass": "db.m1.xlarge",
99
"Engine": "mysql",
100
"EngineVersion": "5.1.57",
101
"LicenseModel": "general-public-license",
102
"MultiAZCapable": True,
103
"ReadReplicaCapable": True,
104
"Vpc": False
105
},
106
{
107
"AvailabilityZones": [
108
{
109
"Name": "us-west-2a",
110
"ProvisionedIopsCapable": True
111
},
112
],
113
"DBInstanceClass": "db.m1.xlarge",
114
"Engine": "mysql",
115
"EngineVersion": "5.1.57",
116
"LicenseModel": "general-public-license",
117
"MultiAZCapable": True,
118
"ReadReplicaCapable": True,
119
"Vpc": True
120
}
121
]
122
}
123
124
LIST_OF_DICTS_TABLE = """\
125
-----------------------------------------------------------------------------------------------------------------------------
126
| OperationName |
127
+---------------------------------------------------------------------------------------------------------------------------+
128
|| OrderableDBInstanceOptions ||
129
|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|
130
|| DBInstanceClass | Engine | EngineVersion | LicenseModel | MultiAZCapable | ReadReplicaCapable | Vpc ||
131
|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|
132
|| db.m1.large | mysql | 5.1.45 | general-public-license | True | True | False ||
133
|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|
134
||| AvailabilityZones |||
135
||+----------------------------------------+------------------------------------------------------------------------------+||
136
||| Name | ProvisionedIopsCapable |||
137
||+----------------------------------------+------------------------------------------------------------------------------+||
138
||| us-east-1a | False |||
139
||| us-east-1d | True |||
140
||+----------------------------------------+------------------------------------------------------------------------------+||
141
|| OrderableDBInstanceOptions ||
142
|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|
143
|| DBInstanceClass | Engine | EngineVersion | LicenseModel | MultiAZCapable | ReadReplicaCapable | Vpc ||
144
|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|
145
|| db.m1.xlarge | mysql | 5.1.57 | general-public-license | True | True | False ||
146
|+-----------------+---------+----------------+-------------------------+-----------------+----------------------+---------+|
147
||| AvailabilityZones |||
148
||+----------------------------------------+------------------------------------------------------------------------------+||
149
||| Name | ProvisionedIopsCapable |||
150
||+----------------------------------------+------------------------------------------------------------------------------+||
151
||| us-west-2a | True |||
152
||| us-west-2b | True |||
153
||+----------------------------------------+------------------------------------------------------------------------------+||
154
|| OrderableDBInstanceOptions ||
155
|+-----------------+---------+----------------+--------------------------+-----------------+----------------------+--------+|
156
|| DBInstanceClass | Engine | EngineVersion | LicenseModel | MultiAZCapable | ReadReplicaCapable | Vpc ||
157
|+-----------------+---------+----------------+--------------------------+-----------------+----------------------+--------+|
158
|| db.m1.xlarge | mysql | 5.1.57 | general-public-license | True | True | True ||
159
|+-----------------+---------+----------------+--------------------------+-----------------+----------------------+--------+|
160
||| AvailabilityZones |||
161
||+----------------------------------------+------------------------------------------------------------------------------+||
162
||| Name | ProvisionedIopsCapable |||
163
||+----------------------------------------+------------------------------------------------------------------------------+||
164
||| us-west-2a | True |||
165
||+----------------------------------------+------------------------------------------------------------------------------+||
166
"""
167
168
169
# First record has "Tags" scalar, second record does not.
170
INNER_LIST = {
171
"Snapshots": [
172
{
173
"Description": "TestVolume1",
174
"Tags": [{"Value": "TestVolume", "Key": "Name"}],
175
"VolumeId": "vol-12345",
176
"State": "completed",
177
"VolumeSize": 8,
178
"Progress": "100%",
179
"StartTime": "2012-05-23T21:46:41.000Z",
180
"SnapshotId": "snap-1234567",
181
"OwnerId": "12345"
182
},
183
{
184
"Description": "Created by CreateImage(i-1234) for ami-1234 from vol-1234",
185
"VolumeId": "vol-e543b98b",
186
"State": "completed",
187
"VolumeSize": 8,
188
"Progress": "100%",
189
"StartTime": "2012-05-25T00:07:20.000Z",
190
"SnapshotId": "snap-23456",
191
"OwnerId": "12345"
192
}
193
]
194
}
195
196
INNER_LIST_TABLE = """\
197
-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
198
| OperationName |
199
+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
200
|| Snapshots ||
201
|+-------------------+--------------+----------------+---------------------+--------------------------------------+-----------------+-----------------+--------------------+|
202
|| Description | OwnerId | Progress | SnapshotId | StartTime | State | VolumeId | VolumeSize ||
203
|+-------------------+--------------+----------------+---------------------+--------------------------------------+-----------------+-----------------+--------------------+|
204
|| TestVolume1 | 12345 | 100% | snap-1234567 | 2012-05-23T21:46:41.000Z | completed | vol-12345 | 8 ||
205
|+-------------------+--------------+----------------+---------------------+--------------------------------------+-----------------+-----------------+--------------------+|
206
||| Tags |||
207
||+-----------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+||
208
||| Key | Value |||
209
||+-----------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+||
210
||| Name | TestVolume |||
211
||+-----------------------------------------------------------+-----------------------------------------------------------------------------------------------------------+||
212
|| Snapshots ||
213
|+------------------------------------------------------------+----------+-----------+-------------+---------------------------+------------+---------------+--------------+|
214
|| Description | OwnerId | Progress | SnapshotId | StartTime | State | VolumeId | VolumeSize ||
215
|+------------------------------------------------------------+----------+-----------+-------------+---------------------------+------------+---------------+--------------+|
216
|| Created by CreateImage(i-1234) for ami-1234 from vol-1234 | 12345 | 100% | snap-23456 | 2012-05-25T00:07:20.000Z | completed | vol-e543b98b | 8 ||
217
|+------------------------------------------------------------+----------+-----------+-------------+---------------------------+------------+---------------+--------------+|
218
"""
219
220
LIST_WITH_MISSING_KEYS = {
221
"Snapshots": [
222
{
223
"Description": "TestVolume1",
224
"Tags": "foo",
225
"VolumeId": "vol-12345",
226
"State": "completed",
227
"VolumeSize": 8,
228
"Progress": "100%",
229
"StartTime": "2012-05-23T21:46:41.000Z",
230
"SnapshotId": "snap-1234567",
231
"OwnerId": "12345"
232
},
233
{
234
"Description": "description",
235
"VolumeId": "vol-e543b98b",
236
"State": "completed",
237
"VolumeSize": 8,
238
"Progress": "100%",
239
"StartTime": "2012-05-25T00:07:20.000Z",
240
"SnapshotId": "snap-23456",
241
"OwnerId": "12345"
242
}
243
]
244
}
245
246
LIST_WITH_MISSING_KEYS_TABLE = """\
247
-----------------------------------------------------------------------------------------------------------------------------------------
248
| OperationName |
249
+---------------------------------------------------------------------------------------------------------------------------------------+
250
|| Snapshots ||
251
|+-------------+----------+-----------+---------------+---------------------------+------------+-------+----------------+--------------+|
252
|| Description | OwnerId | Progress | SnapshotId | StartTime | State | Tags | VolumeId | VolumeSize ||
253
|+-------------+----------+-----------+---------------+---------------------------+------------+-------+----------------+--------------+|
254
|| TestVolume1| 12345 | 100% | snap-1234567 | 2012-05-23T21:46:41.000Z | completed | foo | vol-12345 | 8 ||
255
|| description| 12345 | 100% | snap-23456 | 2012-05-25T00:07:20.000Z | completed | | vol-e543b98b | 8 ||
256
|+-------------+----------+-----------+---------------+---------------------------+------------+-------+----------------+--------------+|
257
"""
258
259
KEYS_NOT_FROM_FIRST_ROW = {
260
"Snapshots": [
261
{
262
"Description": "TestVolume1",
263
"Tags": "foo",
264
"VolumeId": "vol-12345",
265
"State": "completed",
266
"VolumeSize": 8,
267
"Progress": "100%",
268
"StartTime": "start_time",
269
# Missing EndTime.
270
"SnapshotId": "snap-1234567",
271
"OwnerId": "12345"
272
},
273
{
274
"Description": "description",
275
"State": "completed",
276
"VolumeSize": 8,
277
"Progress": "100%",
278
# Missing StartTime
279
"EndTime": "end_time",
280
"SnapshotId": "snap-23456",
281
"OwnerId": "12345"
282
}
283
]
284
}
285
286
KEYS_NOT_FROM_FIRST_ROW_TABLE = """\
287
------------------------------------------------------------------------------------------------------------------------------------
288
| OperationName |
289
+----------------------------------------------------------------------------------------------------------------------------------+
290
|| Snapshots ||
291
|+-------------+-----------+----------+-----------+---------------+-------------+------------+-------+-------------+--------------+|
292
|| Description | EndTime | OwnerId | Progress | SnapshotId | StartTime | State | Tags | VolumeId | VolumeSize ||
293
|+-------------+-----------+----------+-----------+---------------+-------------+------------+-------+-------------+--------------+|
294
|| TestVolume1| | 12345 | 100% | snap-1234567 | start_time | completed | foo | vol-12345 | 8 ||
295
|| description| end_time | 12345 | 100% | snap-23456 | | completed | | | 8 ||
296
|+-------------+-----------+----------+-----------+---------------+-------------+------------+-------+-------------+--------------+|
297
"""
298
299
JMESPATH_FILTERED_RESPONSE = [
300
[
301
[
302
"i-12345",
303
"ami-12345",
304
"ebs",
305
"t1.micro",
306
"running",
307
"disabled",
308
"util"
309
]
310
],
311
[
312
[
313
"i-56789",
314
"ami-56789",
315
"ebs",
316
"c1.medium",
317
"running",
318
"disabled",
319
"myname"
320
]
321
],
322
]
323
JMESPATH_FILTERED_RESPONSE_TABLE = """\
324
-------------------------------------------------------------------------------
325
| OperationName |
326
+---------+------------+------+------------+----------+------------+----------+
327
| i-12345| ami-12345 | ebs | t1.micro | running | disabled | util |
328
| i-56789| ami-56789 | ebs | c1.medium | running | disabled | myname |
329
+---------+------------+------+------------+----------+------------+----------+
330
"""
331
332
333
JMESPATH_FILTERED_RESPONSE_DICT = [
334
[
335
{
336
"InstanceId": "i-12345",
337
"RootDeviceType": "ebs",
338
"InstanceType": "t1.micro",
339
"ImageId": "ami-12345"
340
}
341
],
342
[
343
{
344
"InstanceId": "i-56789",
345
"RootDeviceType": "ebs",
346
"InstanceType": "c1.medium",
347
"ImageId": "ami-56789"
348
}
349
],
350
]
351
352
353
JMESPATH_FILTERED_RESPONSE_DICT_TABLE = """\
354
---------------------------------------------------------------
355
| OperationName |
356
+-----------+-------------+----------------+------------------+
357
| ImageId | InstanceId | InstanceType | RootDeviceType |
358
+-----------+-------------+----------------+------------------+
359
| ami-12345| i-12345 | t1.micro | ebs |
360
| ami-56789| i-56789 | c1.medium | ebs |
361
+-----------+-------------+----------------+------------------+
362
"""
363
364
365
class Object(object):
366
def __init__(self, **kwargs):
367
self.__dict__.update(kwargs)
368
self.query = None
369
370
371
class TestTableFormatter(unittest.TestCase):
372
maxDiff = None
373
374
def setUp(self):
375
styler = Styler()
376
self.table = MultiTable(initial_section=False,
377
column_separator='|', styler=styler,
378
auto_reformat=False)
379
self.formatter = TableFormatter(Object(color='off'))
380
self.formatter.table = self.table
381
self.stream = StringIO()
382
383
def assert_data_renders_to(self, data, table):
384
self.formatter('OperationName', data, stream=self.stream)
385
rendered = self.stream.getvalue()
386
if rendered != table:
387
error_message = ['Expected table rendering does not match '
388
'the actual table rendering:']
389
error_message.append('Expected:')
390
error_message.append(table)
391
error_message.append('Actual:')
392
error_message.append(rendered)
393
self.fail('\n'.join(error_message))
394
395
def test_list_table(self):
396
self.assert_data_renders_to(data=SIMPLE_LIST, table=SIMPLE_LIST_TABLE)
397
398
def test_dict_table(self):
399
self.assert_data_renders_to(data=SIMPLE_DICT, table=SIMPLE_DICT_TABLE)
400
401
def test_list_of_dicts(self):
402
self.assert_data_renders_to(data=LIST_OF_DICTS,
403
table=LIST_OF_DICTS_TABLE)
404
405
def test_inner_table(self):
406
self.assert_data_renders_to(data=INNER_LIST,
407
table=INNER_LIST_TABLE)
408
409
def test_empty_table(self):
410
self.assert_data_renders_to(data={},
411
table='')
412
413
def test_missing_keys(self):
414
self.assert_data_renders_to(data=LIST_WITH_MISSING_KEYS,
415
table=LIST_WITH_MISSING_KEYS_TABLE)
416
417
def test_new_keys_after_first_row(self):
418
self.assert_data_renders_to(data=KEYS_NOT_FROM_FIRST_ROW,
419
table=KEYS_NOT_FROM_FIRST_ROW_TABLE)
420
421
def test_jmespath_filtered_response(self):
422
self.assert_data_renders_to(data=JMESPATH_FILTERED_RESPONSE,
423
table=JMESPATH_FILTERED_RESPONSE_TABLE)
424
425
def test_jmespath_filtered_dict_response(self):
426
self.assert_data_renders_to(data=JMESPATH_FILTERED_RESPONSE_DICT,
427
table=JMESPATH_FILTERED_RESPONSE_DICT_TABLE)
428
429