Merge ~jocave/checkbox-support:netplan-yaml-str-parse into checkbox-support:master

Proposed by Jonathan Cave
Status: Merged
Approved by: Jonathan Cave
Approved revision: 8bbdc3837b3df6ffa2899aa87ad3ef94afe5cba9
Merged at revision: 5c34f8154b289238186baf6a2b3cb4a95558bae6
Proposed branch: ~jocave/checkbox-support:netplan-yaml-str-parse
Merge into: checkbox-support:master
Diff against target: 135 lines (+50/-45)
1 file modified
checkbox_support/parsers/netplan.py (+50/-45)
Reviewer Review Type Date Requested Status
Maciej Kisielewski Approve
Paul Larson Approve
Review via email: mp+370324@code.launchpad.net

Description of the change

Update the netplan parser to allow providing some yaml as string directly. This is useful if you want to provide a config for something other than the system that the code is running on e.g. in some unit tests.

To post a comment you must log in.
Revision history for this message
Paul Larson (pwlars) wrote :

some minor nitpicks and a commented out func def that I think you meant to remove, otherwise looks fine to me

review: Needs Fixing
Revision history for this message
Jonathan Cave (jocave) wrote :

Removed the commented out func def

Revision history for this message
Paul Larson (pwlars) :
review: Approve
Revision history for this message
Maciej Kisielewski (kissiel) wrote :

LGTM, +1

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/checkbox_support/parsers/netplan.py b/checkbox_support/parsers/netplan.py
2index ff49cbf..a9505d2 100644
3--- a/checkbox_support/parsers/netplan.py
4+++ b/checkbox_support/parsers/netplan.py
5@@ -20,6 +20,7 @@
6 # along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
7
8 import glob
9+import io
10 import logging
11 import os
12 import yaml
13@@ -76,23 +77,12 @@ class Netplan():
14 def renderer(self):
15 return self.network['renderer']
16
17- def parse(self):
18+ def parse(self, data=None):
19 """
20 Parse all our config files to return an object that describes the
21 system's entire configuration, so that it can later be interrogated.
22 Returns a dict that contains the entire, collated and merged YAML.
23 """
24-
25- # /run/netplan shadows /etc/netplan/, which shadows /lib/netplan
26- names_to_paths = {}
27- for yaml_dir in ['lib', 'etc', 'run']:
28- for yaml_file in glob.glob(os.path.join(
29- self.prefix, yaml_dir, 'netplan', '*.yaml')):
30- names_to_paths[os.path.basename(yaml_file)] = yaml_file
31-
32- files = [names_to_paths[name]
33- for name in sorted(names_to_paths.keys())]
34-
35 self.config['network'] = {
36 'ethernets': {},
37 'wifis': {},
38@@ -101,8 +91,24 @@ class Netplan():
39 'vlans': {},
40 'renderer': None
41 }
42- for yaml_file in files:
43- self._merge_yaml_config(yaml_file)
44+
45+ if data is None:
46+ # /run/netplan shadows /etc/netplan/, which shadows /lib/netplan
47+ names_to_paths = {}
48+ for yaml_dir in ['lib', 'etc', 'run']:
49+ for yaml_file in glob.glob(os.path.join(
50+ self.prefix, yaml_dir, 'netplan', '*.yaml')):
51+ names_to_paths[os.path.basename(yaml_file)] = yaml_file
52+
53+ files = [names_to_paths[name]
54+ for name in sorted(names_to_paths.keys())]
55+
56+ for yaml_file in files:
57+ with open(yaml_file) as f:
58+ self._merge_yaml_config(f)
59+ else:
60+ with io.StringIO(data) as f:
61+ self._merge_yaml_config(f)
62
63 def _merge_interface_config(self, orig, new):
64 new_interfaces = set()
65@@ -120,40 +126,39 @@ class Netplan():
66
67 return new_interfaces
68
69- def _merge_yaml_config(self, yaml_file):
70+ def _merge_yaml_config(self, yaml_stream):
71 new_interfaces = set()
72
73 try:
74- with open(yaml_file) as f:
75- yaml_data = yaml.load(f, Loader=yaml.CSafeLoader)
76- network = None
77- if yaml_data is not None:
78- network = yaml_data.get('network')
79- if network:
80- if 'ethernets' in network:
81- new = self._merge_interface_config(
82- self.ethernets, network.get('ethernets'))
83- new_interfaces |= new
84- if 'wifis' in network:
85- new = self._merge_interface_config(
86- self.wifis, network.get('wifis'))
87- new_interfaces |= new
88- if 'bridges' in network:
89- new = self._merge_interface_config(
90- self.bridges, network.get('bridges'))
91- new_interfaces |= new
92- if 'bonds' in network:
93- new = self._merge_interface_config(
94- self.bonds, network.get('bonds'))
95- new_interfaces |= new
96- if 'vlans' in network:
97- new = self._merge_interface_config(
98- self.vlans, network.get('vlans'))
99- new_interfaces |= new
100- if 'renderer' in network:
101- self.config['network']['renderer'] = network.get(
102- 'renderer')
103+ yaml_data = yaml.load(yaml_stream, Loader=yaml.CSafeLoader)
104+ network = None
105+ if yaml_data is not None:
106+ network = yaml_data.get('network')
107+ if network:
108+ if 'ethernets' in network:
109+ new = self._merge_interface_config(
110+ self.ethernets, network.get('ethernets'))
111+ new_interfaces |= new
112+ if 'wifis' in network:
113+ new = self._merge_interface_config(
114+ self.wifis, network.get('wifis'))
115+ new_interfaces |= new
116+ if 'bridges' in network:
117+ new = self._merge_interface_config(
118+ self.bridges, network.get('bridges'))
119+ new_interfaces |= new
120+ if 'bonds' in network:
121+ new = self._merge_interface_config(
122+ self.bonds, network.get('bonds'))
123+ new_interfaces |= new
124+ if 'vlans' in network:
125+ new = self._merge_interface_config(
126+ self.vlans, network.get('vlans'))
127+ new_interfaces |= new
128+ if 'renderer' in network:
129+ self.config['network']['renderer'] = network.get(
130+ 'renderer')
131 return new_interfaces
132 except (IOError, yaml.YAMLError):
133- logging.error('Error while loading {}'.format(yaml_file))
134+ logging.error('Error while loading yaml')
135 self.config = {}

Subscribers

People subscribed via source and target branches