Browse Source

support localconf set

Sean Dague 2 years ago
parent
commit
de574dc6a8
2 changed files with 174 additions and 0 deletions
  1. 59
    0
      devstack/dsconf.py
  2. 115
    0
      devstack/tests/test_localconf_set.py

+ 59
- 0
devstack/dsconf.py View File

@@ -211,3 +211,62 @@ class LocalConf(object):
211 211
         def _do_set(writer, line):
212 212
             writer.write("%s = %s\n" % (name, value))
213 213
         self._at_insert_point_local(name, _do_set)
214
+
215
+    def _at_insert_point(self, group, conf, section, name, func):
216
+        temp = tempfile.NamedTemporaryFile(mode='r')
217
+        shutil.copyfile(self.fname, temp.name)
218
+        in_meta = False
219
+        in_section = False
220
+        done = False
221
+        with open(self.fname, "w+") as writer:
222
+            with open(temp.name) as reader:
223
+                for line in reader.readlines():
224
+                    if done:
225
+                        writer.write(line)
226
+                        continue
227
+
228
+                    if re.match(re.escape("[[%s|%s]]" % (group, conf)), line):
229
+                        in_meta = True
230
+                        writer.write(line)
231
+                    elif re.match("\[\[.*\|.*\]\]", line):
232
+                        # if we're not done yet, we
233
+                        if in_meta:
234
+                            if not in_section:
235
+                                # if we've not found the section yet,
236
+                                # write out section as well.
237
+                                writer.write("[%s]\n" % section)
238
+                            func(writer, None)
239
+                            done = True
240
+                        writer.write(line)
241
+                        in_meta = False
242
+                        in_section = False
243
+                    elif re.match(re.escape("[%s]" % section), line):
244
+                        # we found a relevant section
245
+                        writer.write(line)
246
+                        in_section = True
247
+                    elif re.match("\[[^\[\]]+\]", line):
248
+                        if in_meta and in_section:
249
+                            # We've ended our section, in our meta,
250
+                            # never found the key. Time to add it.
251
+                            func(writer, None)
252
+                            done = True
253
+                        in_section = False
254
+                        writer.write(line)
255
+                    elif (in_meta and in_section and
256
+                          re.match("\s*%s\s*\=" % re.escape(name), line)):
257
+                        # we found our match point
258
+                        func(writer, line)
259
+                        done = True
260
+                    else:
261
+                        # write out whatever we find
262
+                        writer.write(line)
263
+            if not done:
264
+                # we never found meta with a relevant section
265
+                writer.write("[[%s|%s]]\n" % (group, conf))
266
+                writer.write("[%s]\n" % (section))
267
+                func(writer, None)
268
+
269
+    def set(self, group, conf, section, name, value):
270
+        def _do_set(writer, line):
271
+            writer.write("%s = %s\n" % (name, value))
272
+        self._at_insert_point(group, conf, section, name, _do_set)

+ 115
- 0
devstack/tests/test_localconf_set.py View File

@@ -0,0 +1,115 @@
1
+# Copyright 2017 IBM
2
+#
3
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
4
+# not use this file except in compliance with the License. You may obtain
5
+# a copy of the License at
6
+#
7
+#    http://www.apache.org/licenses/LICENSE-2.0
8
+#
9
+# Unless required by applicable law or agreed to in writing, software
10
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12
+# License for the specific language governing permissions and limitations
13
+# under the License.
14
+
15
+# Implementation of ini add / remove for devstack. We don't use the
16
+# python ConfigFile parser because that ends up rewriting the entire
17
+# file and doesn't ensure comments remain.
18
+
19
+import fixtures
20
+import os.path
21
+import testtools
22
+
23
+from devstack import dsconf
24
+
25
+
26
+BASIC = """
27
+[[local|localrc]]
28
+a = b
29
+c = d
30
+f = 1
31
+[[post-config|$NEUTRON_CONF]]
32
+[DEFAULT]
33
+global_physnet_mtu=1450
34
+[[post-config|$NOVA_CONF]]
35
+[upgrade_levels]
36
+compute = auto
37
+"""
38
+
39
+RESULT1 = """
40
+[[local|localrc]]
41
+a = b
42
+c = d
43
+f = 1
44
+[[post-config|$NEUTRON_CONF]]
45
+[DEFAULT]
46
+global_physnet_mtu = 1400
47
+[[post-config|$NOVA_CONF]]
48
+[upgrade_levels]
49
+compute = auto
50
+"""
51
+
52
+RESULT2 = """
53
+[[local|localrc]]
54
+a = b
55
+c = d
56
+f = 1
57
+[[post-config|$NEUTRON_CONF]]
58
+[DEFAULT]
59
+global_physnet_mtu=1450
60
+[oslo_policy]
61
+policy_file = /etc/neutron/policy.json
62
+[[post-config|$NOVA_CONF]]
63
+[upgrade_levels]
64
+compute = auto
65
+"""
66
+
67
+RESULT3 = """
68
+[[local|localrc]]
69
+a = b
70
+c = d
71
+f = 1
72
+[[post-config|$NEUTRON_CONF]]
73
+[DEFAULT]
74
+global_physnet_mtu=1450
75
+[[post-config|$NOVA_CONF]]
76
+[upgrade_levels]
77
+compute = auto
78
+[[post-config|$GLANCE_CONF]]
79
+[DEFAULT]
80
+graceful_shutdown_timeout = 5
81
+"""
82
+
83
+
84
+class TestLcSet(testtools.TestCase):
85
+
86
+    def setUp(self):
87
+        super(TestLcSet, self).setUp()
88
+        self._path = self.useFixture(fixtures.TempDir()).path
89
+        self._path += "/local.conf"
90
+        with open(self._path, "w") as f:
91
+            f.write(BASIC)
92
+
93
+    def test_set_existing(self):
94
+        conf = dsconf.LocalConf(self._path)
95
+        conf.set("post-config", "$NEUTRON_CONF", "DEFAULT",
96
+                 "global_physnet_mtu", "1400")
97
+        with open(self._path) as f:
98
+            content = f.read()
99
+            self.assertEqual(content, RESULT1)
100
+
101
+    def test_set_new(self):
102
+        conf = dsconf.LocalConf(self._path)
103
+        conf.set("post-config", "$NEUTRON_CONF", "oslo_policy",
104
+                 "policy_file", "/etc/neutron/policy.json")
105
+        with open(self._path) as f:
106
+            content = f.read()
107
+            self.assertEqual(content, RESULT2)
108
+
109
+    def test_set_new_section(self):
110
+        conf = dsconf.LocalConf(self._path)
111
+        conf.set("post-config", "$GLANCE_CONF", "DEFAULT",
112
+                 "graceful_shutdown_timeout", "5")
113
+        with open(self._path) as f:
114
+            content = f.read()
115
+            self.assertEqual(content, RESULT3)

Loading…
Cancel
Save