Merge ~chad.smith/cloud-init:simpletable-getstring-fix into cloud-init:master

Proposed by Chad Smith
Status: Merged
Approved by: Chad Smith
Approved revision: daf5dd118451bef3216c440b10650b26233cc9fd
Merged at revision: d4f70470b7c3af89d4bf97123f4d61ad8a58805b
Proposed branch: ~chad.smith/cloud-init:simpletable-getstring-fix
Merge into: cloud-init:master
Diff against target: 151 lines (+115/-3)
4 files modified
cloudinit/netinfo.py (+1/-1)
cloudinit/simpletable.py (+1/-1)
cloudinit/tests/test_netinfo.py (+106/-0)
cloudinit/tests/test_simpletable.py (+7/-1)
Reviewer Review Type Date Requested Status
Scott Moser Approve
Server Team CI bot continuous-integration Approve
Review via email: mp+332066@code.launchpad.net

Description of the change

simpletable: Fix get_string method to return table-formatted string

Output in cloud-init-output.log contained only the string representation
of a SimpleTable object instead of the table formatted content. This bug
also affected ssh_authkey_fingerprints.

LP: #1722566

To post a comment you must log in.
Revision history for this message
Server Team CI bot (server-team-bot) wrote :

FAILED: Continuous integration, rev:daf5dd118451bef3216c440b10650b26233cc9fd
https://jenkins.ubuntu.com/server/job/cloud-init-ci/398/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    FAILED: MAAS Compatability Testing

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/398/rebuild

review: Needs Fixing (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

need to make sure the failure there is just noise... looks like it was,
and doesn't seem like it should be related.

the code looks good and thanks for the tests.

I am running a test here just quick to verify we get
the network output rendered.

I ran a integration test with:
$ tox -e citest -- run --preserve-data --data-dir=/tmp/artifacts --deb=/home/smoser-public/src/cloud-init/build/../cloud-init_17.1-20-gdaf5dd11-1~bddeb_all.deb --verbose --os-name=xenial --test=modules/final_message

and then verify that /tmp/artifacts/lxd/xenial/modules/final_message/cloud-init-output.log had the
messages we wanted. see
 http://paste.ubuntu.com/25714903/

Revision history for this message
Ryan Harper (raharper) :
Revision history for this message
Scott Moser (smoser) wrote :

wait on the re-build to post results and then lets get this and upload.

Revision history for this message
Server Team CI bot (server-team-bot) wrote :

PASSED: Continuous integration, rev:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/399/
Executed test runs:
    SUCCESS: Checkout
    SUCCESS: Unit & Style Tests
    SUCCESS: Ubuntu LTS: Build
    SUCCESS: Ubuntu LTS: Integration
    SUCCESS: MAAS Compatability Testing
    IN_PROGRESS: Declarative: Post Actions

Click here to trigger a rebuild:
https://jenkins.ubuntu.com/server/job/cloud-init-ci/399/rebuild

review: Approve (continuous-integration)
Revision history for this message
Scott Moser (smoser) wrote :

I approve.
wrt Ryan's comment, i agree that the 80 chars is annoying here, but i think we should just leave as is to get it in.

Revision history for this message
Scott Moser (smoser) :
review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/cloudinit/netinfo.py b/cloudinit/netinfo.py
2index 8f99d99..993b26c 100644
3--- a/cloudinit/netinfo.py
4+++ b/cloudinit/netinfo.py
5@@ -171,7 +171,7 @@ def netdev_pformat():
6 else:
7 fields = ['Device', 'Up', 'Address', 'Mask', 'Scope', 'Hw-Address']
8 tbl = SimpleTable(fields)
9- for (dev, d) in netdev.items():
10+ for (dev, d) in sorted(netdev.items()):
11 tbl.add_row([dev, d["up"], d["addr"], d["mask"], ".", d["hwaddr"]])
12 if d.get('addr6'):
13 tbl.add_row([dev, d["up"],
14diff --git a/cloudinit/simpletable.py b/cloudinit/simpletable.py
15index 9060322..ca663cc 100644
16--- a/cloudinit/simpletable.py
17+++ b/cloudinit/simpletable.py
18@@ -59,4 +59,4 @@ class SimpleTable(object):
19 return '\n'.join(lines)
20
21 def get_string(self):
22- return repr(self)
23+ return self.__str__()
24diff --git a/cloudinit/tests/test_netinfo.py b/cloudinit/tests/test_netinfo.py
25new file mode 100644
26index 0000000..7dea2e4
27--- /dev/null
28+++ b/cloudinit/tests/test_netinfo.py
29@@ -0,0 +1,106 @@
30+# This file is part of cloud-init. See LICENSE file for license information.
31+
32+"""Tests netinfo module functions and classes."""
33+
34+from cloudinit.netinfo import netdev_pformat, route_pformat
35+from cloudinit.tests.helpers import CiTestCase, mock
36+
37+
38+# Example ifconfig and route output
39+SAMPLE_IFCONFIG_OUT = """\
40+enp0s25 Link encap:Ethernet HWaddr 50:7b:9d:2c:af:91
41+ inet addr:192.168.2.18 Bcast:192.168.2.255 Mask:255.255.255.0
42+ inet6 addr: fe80::8107:2b92:867e:f8a6/64 Scope:Link
43+ UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
44+ RX packets:8106427 errors:55 dropped:0 overruns:0 frame:37
45+ TX packets:9339739 errors:0 dropped:0 overruns:0 carrier:0
46+ collisions:0 txqueuelen:1000
47+ RX bytes:4953721719 (4.9 GB) TX bytes:7731890194 (7.7 GB)
48+ Interrupt:20 Memory:e1200000-e1220000
49+
50+lo Link encap:Local Loopback
51+ inet addr:127.0.0.1 Mask:255.0.0.0
52+ inet6 addr: ::1/128 Scope:Host
53+ UP LOOPBACK RUNNING MTU:65536 Metric:1
54+ RX packets:579230851 errors:0 dropped:0 overruns:0 frame:0
55+ TX packets:579230851 errors:0 dropped:0 overruns:0 carrier:0
56+ collisions:0 txqueuelen:1
57+"""
58+
59+SAMPLE_ROUTE_OUT = '\n'.join([
60+ '0.0.0.0 192.168.2.1 0.0.0.0 UG 0 0 0'
61+ ' enp0s25',
62+ '0.0.0.0 192.168.2.1 0.0.0.0 UG 0 0 0'
63+ ' wlp3s0',
64+ '192.168.2.0 0.0.0.0 255.255.255.0 U 0 0 0'
65+ ' enp0s25'])
66+
67+
68+NETDEV_FORMATTED_OUT = '\n'.join([
69+ '+++++++++++++++++++++++++++++++++++++++Net device info+++++++++++++++++++'
70+ '++++++++++++++++++++',
71+ '+---------+------+------------------------------+---------------+-------+'
72+ '-------------------+',
73+ '| Device | Up | Address | Mask | Scope |'
74+ ' Hw-Address |',
75+ '+---------+------+------------------------------+---------------+-------+'
76+ '-------------------+',
77+ '| enp0s25 | True | 192.168.2.18 | 255.255.255.0 | . |'
78+ ' 50:7b:9d:2c:af:91 |',
79+ '| enp0s25 | True | fe80::8107:2b92:867e:f8a6/64 | . | link |'
80+ ' 50:7b:9d:2c:af:91 |',
81+ '| lo | True | 127.0.0.1 | 255.0.0.0 | . |'
82+ ' . |',
83+ '| lo | True | ::1/128 | . | host |'
84+ ' . |',
85+ '+---------+------+------------------------------+---------------+-------+'
86+ '-------------------+'])
87+
88+ROUTE_FORMATTED_OUT = '\n'.join([
89+ '+++++++++++++++++++++++++++++Route IPv4 info++++++++++++++++++++++++++'
90+ '+++',
91+ '+-------+-------------+-------------+---------------+-----------+-----'
92+ '--+',
93+ '| Route | Destination | Gateway | Genmask | Interface | Flags'
94+ ' |',
95+ '+-------+-------------+-------------+---------------+-----------+'
96+ '-------+',
97+ '| 0 | 0.0.0.0 | 192.168.2.1 | 0.0.0.0 | wlp3s0 |'
98+ ' UG |',
99+ '| 1 | 192.168.2.0 | 0.0.0.0 | 255.255.255.0 | enp0s25 |'
100+ ' U |',
101+ '+-------+-------------+-------------+---------------+-----------+'
102+ '-------+',
103+ '++++++++++++++++++++++++++++++++++++++++Route IPv6 info++++++++++'
104+ '++++++++++++++++++++++++++++++',
105+ '+-------+-------------+-------------+---------------+---------------+'
106+ '-----------------+-------+',
107+ '| Route | Proto | Recv-Q | Send-Q | Local Address |'
108+ ' Foreign Address | State |',
109+ '+-------+-------------+-------------+---------------+---------------+'
110+ '-----------------+-------+',
111+ '| 0 | 0.0.0.0 | 192.168.2.1 | 0.0.0.0 | UG |'
112+ ' 0 | 0 |',
113+ '| 1 | 192.168.2.0 | 0.0.0.0 | 255.255.255.0 | U |'
114+ ' 0 | 0 |',
115+ '+-------+-------------+-------------+---------------+---------------+'
116+ '-----------------+-------+'])
117+
118+
119+class TestNetInfo(CiTestCase):
120+
121+ maxDiff = None
122+
123+ @mock.patch('cloudinit.netinfo.util.subp')
124+ def test_netdev_pformat(self, m_subp):
125+ """netdev_pformat properly rendering network device information."""
126+ m_subp.return_value = (SAMPLE_IFCONFIG_OUT, '')
127+ content = netdev_pformat()
128+ self.assertEqual(NETDEV_FORMATTED_OUT, content)
129+
130+ @mock.patch('cloudinit.netinfo.util.subp')
131+ def test_route_pformat(self, m_subp):
132+ """netdev_pformat properly rendering network device information."""
133+ m_subp.return_value = (SAMPLE_ROUTE_OUT, '')
134+ content = route_pformat()
135+ self.assertEqual(ROUTE_FORMATTED_OUT, content)
136diff --git a/cloudinit/tests/test_simpletable.py b/cloudinit/tests/test_simpletable.py
137index 96bc24c..a12a62a 100644
138--- a/cloudinit/tests/test_simpletable.py
139+++ b/cloudinit/tests/test_simpletable.py
140@@ -97,4 +97,10 @@ class TestSimpleTable(CiTestCase):
141 table = SimpleTable(AUTHORIZED_KEYS_FIELDS)
142 for row in AUTHORIZED_KEYS_ROWS:
143 table.add_row(row)
144- self.assertEqual(str(table), AUTHORIZED_KEYS_TABLE)
145+
146+ def test_get_string(self):
147+ """get_string() method returns the same content as str()."""
148+ table = SimpleTable(AUTHORIZED_KEYS_FIELDS)
149+ for row in AUTHORIZED_KEYS_ROWS:
150+ table.add_row(row)
151+ self.assertEqual(table.get_string(), str(table))

Subscribers

People subscribed via source and target branches