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
diff --git a/checkbox_support/parsers/netplan.py b/checkbox_support/parsers/netplan.py
index ff49cbf..a9505d2 100644
--- a/checkbox_support/parsers/netplan.py
+++ b/checkbox_support/parsers/netplan.py
@@ -20,6 +20,7 @@
20# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.20# along with Checkbox. If not, see <http://www.gnu.org/licenses/>.
2121
22import glob22import glob
23import io
23import logging24import logging
24import os25import os
25import yaml26import yaml
@@ -76,23 +77,12 @@ class Netplan():
76 def renderer(self):77 def renderer(self):
77 return self.network['renderer']78 return self.network['renderer']
7879
79 def parse(self):80 def parse(self, data=None):
80 """81 """
81 Parse all our config files to return an object that describes the82 Parse all our config files to return an object that describes the
82 system's entire configuration, so that it can later be interrogated.83 system's entire configuration, so that it can later be interrogated.
83 Returns a dict that contains the entire, collated and merged YAML.84 Returns a dict that contains the entire, collated and merged YAML.
84 """85 """
85
86 # /run/netplan shadows /etc/netplan/, which shadows /lib/netplan
87 names_to_paths = {}
88 for yaml_dir in ['lib', 'etc', 'run']:
89 for yaml_file in glob.glob(os.path.join(
90 self.prefix, yaml_dir, 'netplan', '*.yaml')):
91 names_to_paths[os.path.basename(yaml_file)] = yaml_file
92
93 files = [names_to_paths[name]
94 for name in sorted(names_to_paths.keys())]
95
96 self.config['network'] = {86 self.config['network'] = {
97 'ethernets': {},87 'ethernets': {},
98 'wifis': {},88 'wifis': {},
@@ -101,8 +91,24 @@ class Netplan():
101 'vlans': {},91 'vlans': {},
102 'renderer': None92 'renderer': None
103 }93 }
104 for yaml_file in files:94
105 self._merge_yaml_config(yaml_file)95 if data is None:
96 # /run/netplan shadows /etc/netplan/, which shadows /lib/netplan
97 names_to_paths = {}
98 for yaml_dir in ['lib', 'etc', 'run']:
99 for yaml_file in glob.glob(os.path.join(
100 self.prefix, yaml_dir, 'netplan', '*.yaml')):
101 names_to_paths[os.path.basename(yaml_file)] = yaml_file
102
103 files = [names_to_paths[name]
104 for name in sorted(names_to_paths.keys())]
105
106 for yaml_file in files:
107 with open(yaml_file) as f:
108 self._merge_yaml_config(f)
109 else:
110 with io.StringIO(data) as f:
111 self._merge_yaml_config(f)
106112
107 def _merge_interface_config(self, orig, new):113 def _merge_interface_config(self, orig, new):
108 new_interfaces = set()114 new_interfaces = set()
@@ -120,40 +126,39 @@ class Netplan():
120126
121 return new_interfaces127 return new_interfaces
122128
123 def _merge_yaml_config(self, yaml_file):129 def _merge_yaml_config(self, yaml_stream):
124 new_interfaces = set()130 new_interfaces = set()
125131
126 try:132 try:
127 with open(yaml_file) as f:133 yaml_data = yaml.load(yaml_stream, Loader=yaml.CSafeLoader)
128 yaml_data = yaml.load(f, Loader=yaml.CSafeLoader)134 network = None
129 network = None135 if yaml_data is not None:
130 if yaml_data is not None:136 network = yaml_data.get('network')
131 network = yaml_data.get('network')137 if network:
132 if network:138 if 'ethernets' in network:
133 if 'ethernets' in network:139 new = self._merge_interface_config(
134 new = self._merge_interface_config(140 self.ethernets, network.get('ethernets'))
135 self.ethernets, network.get('ethernets'))141 new_interfaces |= new
136 new_interfaces |= new142 if 'wifis' in network:
137 if 'wifis' in network:143 new = self._merge_interface_config(
138 new = self._merge_interface_config(144 self.wifis, network.get('wifis'))
139 self.wifis, network.get('wifis'))145 new_interfaces |= new
140 new_interfaces |= new146 if 'bridges' in network:
141 if 'bridges' in network:147 new = self._merge_interface_config(
142 new = self._merge_interface_config(148 self.bridges, network.get('bridges'))
143 self.bridges, network.get('bridges'))149 new_interfaces |= new
144 new_interfaces |= new150 if 'bonds' in network:
145 if 'bonds' in network:151 new = self._merge_interface_config(
146 new = self._merge_interface_config(152 self.bonds, network.get('bonds'))
147 self.bonds, network.get('bonds'))153 new_interfaces |= new
148 new_interfaces |= new154 if 'vlans' in network:
149 if 'vlans' in network:155 new = self._merge_interface_config(
150 new = self._merge_interface_config(156 self.vlans, network.get('vlans'))
151 self.vlans, network.get('vlans'))157 new_interfaces |= new
152 new_interfaces |= new158 if 'renderer' in network:
153 if 'renderer' in network:159 self.config['network']['renderer'] = network.get(
154 self.config['network']['renderer'] = network.get(160 'renderer')
155 'renderer')
156 return new_interfaces161 return new_interfaces
157 except (IOError, yaml.YAMLError):162 except (IOError, yaml.YAMLError):
158 logging.error('Error while loading {}'.format(yaml_file))163 logging.error('Error while loading yaml')
159 self.config = {}164 self.config = {}

Subscribers

People subscribed via source and target branches