blob: 7c526b34c825654ce7bcb4b6ecdbd08fb7347cc8 [file] [log] [blame]
James E. Blair6f27fca2017-11-21 17:05:43 -08001# Copyright (C) 2017 Red Hat, Inc.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain 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,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
12# implied.
13#
14# See the License for the specific language governing permissions and
15# limitations under the License.
16
17import os
18import shutil
19import tempfile
20import unittest
21
22from devstack_local_conf import LocalConf
23from collections import OrderedDict
24
25class TestDevstackLocalConf(unittest.TestCase):
Luigi Toscano70d043d2019-03-12 22:25:44 +010026
27 @staticmethod
28 def _init_localconf(p):
29 lc = LocalConf(p.get('localrc'),
30 p.get('local_conf'),
31 p.get('base_services'),
32 p.get('services'),
33 p.get('plugins'),
34 p.get('base_dir'),
35 p.get('projects'),
36 p.get('project'),
37 p.get('tempest_plugins'))
38 return lc
39
James E. Blair6f27fca2017-11-21 17:05:43 -080040 def setUp(self):
41 self.tmpdir = tempfile.mkdtemp()
42
43 def tearDown(self):
44 shutil.rmtree(self.tmpdir)
45
46 def test_plugins(self):
47 "Test that plugins without dependencies work"
48 localrc = {'test_localrc': '1'}
49 local_conf = {'install':
50 {'nova.conf':
51 {'main':
52 {'test_conf': '2'}}}}
53 services = {'cinder': True}
54 # We use ordereddict here to make sure the plugins are in the
55 # *wrong* order for testing.
56 plugins = OrderedDict([
Ian Wienand8b003e02019-03-04 16:50:42 +110057 ('bar', 'https://git.openstack.org/openstack/bar-plugin'),
58 ('foo', 'https://git.openstack.org/openstack/foo-plugin'),
59 ('baz', 'https://git.openstack.org/openstack/baz-plugin'),
James E. Blair6f27fca2017-11-21 17:05:43 -080060 ])
61 p = dict(localrc=localrc,
62 local_conf=local_conf,
63 base_services=[],
64 services=services,
65 plugins=plugins,
66 base_dir='./test',
67 path=os.path.join(self.tmpdir, 'test.local.conf'))
Luigi Toscano70d043d2019-03-12 22:25:44 +010068 lc = self._init_localconf(p)
James E. Blair6f27fca2017-11-21 17:05:43 -080069 lc.write(p['path'])
70
71 plugins = []
72 with open(p['path']) as f:
73 for line in f:
74 if line.startswith('enable_plugin'):
75 plugins.append(line.split()[1])
76 self.assertEqual(['bar', 'baz', 'foo'], plugins)
77
James E. Blaire1edde32018-03-02 15:05:14 +000078
James E. Blair6f27fca2017-11-21 17:05:43 -080079 def test_plugin_deps(self):
80 "Test that plugins with dependencies work"
81 os.makedirs(os.path.join(self.tmpdir, 'foo-plugin', 'devstack'))
82 os.makedirs(os.path.join(self.tmpdir, 'foo-plugin', '.git'))
83 os.makedirs(os.path.join(self.tmpdir, 'bar-plugin', 'devstack'))
84 os.makedirs(os.path.join(self.tmpdir, 'bar-plugin', '.git'))
85 with open(os.path.join(
86 self.tmpdir,
87 'foo-plugin', 'devstack', 'settings'), 'w') as f:
Jens Harbott0b855002018-12-19 12:20:51 +000088 f.write('define_plugin foo-plugin\n')
James E. Blair6f27fca2017-11-21 17:05:43 -080089 with open(os.path.join(
90 self.tmpdir,
91 'bar-plugin', 'devstack', 'settings'), 'w') as f:
Jens Harbott0b855002018-12-19 12:20:51 +000092 f.write('define_plugin bar-plugin\n')
93 f.write('plugin_requires bar-plugin foo-plugin\n')
James E. Blair6f27fca2017-11-21 17:05:43 -080094
95 localrc = {'test_localrc': '1'}
96 local_conf = {'install':
97 {'nova.conf':
98 {'main':
99 {'test_conf': '2'}}}}
100 services = {'cinder': True}
101 # We use ordereddict here to make sure the plugins are in the
102 # *wrong* order for testing.
103 plugins = OrderedDict([
Ian Wienand8b003e02019-03-04 16:50:42 +1100104 ('bar-plugin', 'https://git.openstack.org/openstack/bar-plugin'),
105 ('foo-plugin', 'https://git.openstack.org/openstack/foo-plugin'),
James E. Blair6f27fca2017-11-21 17:05:43 -0800106 ])
107 p = dict(localrc=localrc,
108 local_conf=local_conf,
109 base_services=[],
110 services=services,
111 plugins=plugins,
112 base_dir=self.tmpdir,
113 path=os.path.join(self.tmpdir, 'test.local.conf'))
Luigi Toscano70d043d2019-03-12 22:25:44 +0100114 lc = self._init_localconf(p)
Jens Harbott6d103a72018-12-19 11:53:16 +0000115 lc.write(p['path'])
116
117 plugins = []
118 with open(p['path']) as f:
119 for line in f:
120 if line.startswith('enable_plugin'):
121 plugins.append(line.split()[1])
Jens Harbott0b855002018-12-19 12:20:51 +0000122 self.assertEqual(['foo-plugin', 'bar-plugin'], plugins)
James E. Blaire1edde32018-03-02 15:05:14 +0000123
124 def test_libs_from_git(self):
125 "Test that LIBS_FROM_GIT is auto-generated"
126 projects = {
127 'git.openstack.org/openstack/nova': {
128 'required': True,
129 'short_name': 'nova',
130 },
131 'git.openstack.org/openstack/oslo.messaging': {
132 'required': True,
133 'short_name': 'oslo.messaging',
134 },
135 'git.openstack.org/openstack/devstack-plugin': {
136 'required': False,
137 'short_name': 'devstack-plugin',
138 },
139 }
James E. Blair8e5f8c22018-06-15 10:10:35 -0700140 project = {
141 'short_name': 'glance',
142 }
James E. Blaire1edde32018-03-02 15:05:14 +0000143 p = dict(base_services=[],
144 base_dir='./test',
145 path=os.path.join(self.tmpdir, 'test.local.conf'),
James E. Blair8e5f8c22018-06-15 10:10:35 -0700146 projects=projects,
147 project=project)
Luigi Toscano70d043d2019-03-12 22:25:44 +0100148 lc = self._init_localconf(p)
James E. Blair6f27fca2017-11-21 17:05:43 -0800149 lc.write(p['path'])
150
James E. Blaire1edde32018-03-02 15:05:14 +0000151 lfg = None
James E. Blair6f27fca2017-11-21 17:05:43 -0800152 with open(p['path']) as f:
153 for line in f:
James E. Blaire1edde32018-03-02 15:05:14 +0000154 if line.startswith('LIBS_FROM_GIT'):
155 lfg = line.strip().split('=')[1]
James E. Blair8e5f8c22018-06-15 10:10:35 -0700156 self.assertEqual('nova,oslo.messaging,glance', lfg)
James E. Blaire1edde32018-03-02 15:05:14 +0000157
158 def test_overridelibs_from_git(self):
159 "Test that LIBS_FROM_GIT can be overridden"
160 localrc = {'LIBS_FROM_GIT': 'oslo.db'}
161 projects = {
162 'git.openstack.org/openstack/nova': {
163 'required': True,
164 'short_name': 'nova',
165 },
166 'git.openstack.org/openstack/oslo.messaging': {
167 'required': True,
168 'short_name': 'oslo.messaging',
169 },
170 'git.openstack.org/openstack/devstack-plugin': {
171 'required': False,
172 'short_name': 'devstack-plugin',
173 },
174 }
175 p = dict(localrc=localrc,
176 base_services=[],
177 base_dir='./test',
178 path=os.path.join(self.tmpdir, 'test.local.conf'),
179 projects=projects)
Luigi Toscano70d043d2019-03-12 22:25:44 +0100180 lc = self._init_localconf(p)
James E. Blaire1edde32018-03-02 15:05:14 +0000181 lc.write(p['path'])
182
183 lfg = None
184 with open(p['path']) as f:
185 for line in f:
186 if line.startswith('LIBS_FROM_GIT'):
187 lfg = line.strip().split('=')[1]
Ian Wienande7693482019-02-11 12:26:03 +1100188 self.assertEqual('"oslo.db"', lfg)
James E. Blair6f27fca2017-11-21 17:05:43 -0800189
Jens Harbott7f0b4f32019-04-01 11:43:28 +0000190 def test_avoid_double_quote(self):
191 "Test that there a no duplicated quotes"
192 localrc = {'TESTVAR': '"quoted value"'}
193 p = dict(localrc=localrc,
194 base_services=[],
195 base_dir='./test',
196 path=os.path.join(self.tmpdir, 'test.local.conf'),
197 projects={})
198 lc = self._init_localconf(p)
199 lc.write(p['path'])
200
201 testvar = None
202 with open(p['path']) as f:
203 for line in f:
204 if line.startswith('TESTVAR'):
205 testvar = line.strip().split('=')[1]
206 self.assertEqual('"quoted value"', testvar)
207
James E. Blair6f27fca2017-11-21 17:05:43 -0800208 def test_plugin_circular_deps(self):
209 "Test that plugins with circular dependencies fail"
210 os.makedirs(os.path.join(self.tmpdir, 'foo-plugin', 'devstack'))
211 os.makedirs(os.path.join(self.tmpdir, 'foo-plugin', '.git'))
212 os.makedirs(os.path.join(self.tmpdir, 'bar-plugin', 'devstack'))
213 os.makedirs(os.path.join(self.tmpdir, 'bar-plugin', '.git'))
214 with open(os.path.join(
215 self.tmpdir,
216 'foo-plugin', 'devstack', 'settings'), 'w') as f:
217 f.write('define_plugin foo\n')
218 f.write('plugin_requires foo bar\n')
219 with open(os.path.join(
220 self.tmpdir,
221 'bar-plugin', 'devstack', 'settings'), 'w') as f:
222 f.write('define_plugin bar\n')
223 f.write('plugin_requires bar foo\n')
224
225 localrc = {'test_localrc': '1'}
226 local_conf = {'install':
227 {'nova.conf':
228 {'main':
229 {'test_conf': '2'}}}}
230 services = {'cinder': True}
231 # We use ordereddict here to make sure the plugins are in the
232 # *wrong* order for testing.
233 plugins = OrderedDict([
Ian Wienand8b003e02019-03-04 16:50:42 +1100234 ('bar', 'https://git.openstack.org/openstack/bar-plugin'),
235 ('foo', 'https://git.openstack.org/openstack/foo-plugin'),
James E. Blair6f27fca2017-11-21 17:05:43 -0800236 ])
237 p = dict(localrc=localrc,
238 local_conf=local_conf,
239 base_services=[],
240 services=services,
241 plugins=plugins,
242 base_dir=self.tmpdir,
243 path=os.path.join(self.tmpdir, 'test.local.conf'))
244 with self.assertRaises(Exception):
Luigi Toscano70d043d2019-03-12 22:25:44 +0100245 lc = self._init_localconf(p)
James E. Blair6f27fca2017-11-21 17:05:43 -0800246 lc.write(p['path'])
247
Luigi Toscano70d043d2019-03-12 22:25:44 +0100248 def _find_tempest_plugins_value(self, file_path):
249 tp = None
250 with open(file_path) as f:
251 for line in f:
252 if line.startswith('TEMPEST_PLUGINS'):
253 found = line.strip().split('=')[1]
254 self.assertIsNone(tp,
255 "TEMPEST_PLUGIN ({}) found again ({})".format(
256 tp, found))
257 tp = found
258 return tp
259
260 def test_tempest_plugins(self):
261 "Test that TEMPEST_PLUGINS is correctly populated."
262 p = dict(base_services=[],
263 base_dir='./test',
264 path=os.path.join(self.tmpdir, 'test.local.conf'),
265 tempest_plugins=['heat-tempest-plugin', 'sahara-tests'])
266 lc = self._init_localconf(p)
267 lc.write(p['path'])
268
269 tp = self._find_tempest_plugins_value(p['path'])
270 self.assertEqual('"./test/heat-tempest-plugin ./test/sahara-tests"', tp)
271 self.assertEqual(len(lc.warnings), 0)
272
273 def test_tempest_plugins_not_overridden(self):
274 """Test that the existing value of TEMPEST_PLUGINS is not overridden
275 by the user-provided value, but a warning is emitted."""
276 localrc = {'TEMPEST_PLUGINS': 'someplugin'}
277 p = dict(localrc=localrc,
278 base_services=[],
279 base_dir='./test',
280 path=os.path.join(self.tmpdir, 'test.local.conf'),
281 tempest_plugins=['heat-tempest-plugin', 'sahara-tests'])
282 lc = self._init_localconf(p)
283 lc.write(p['path'])
284
285 tp = self._find_tempest_plugins_value(p['path'])
Ian Wienande7693482019-02-11 12:26:03 +1100286 self.assertEqual('"someplugin"', tp)
Luigi Toscano70d043d2019-03-12 22:25:44 +0100287 self.assertEqual(len(lc.warnings), 1)
288
James E. Blair6f27fca2017-11-21 17:05:43 -0800289
290if __name__ == '__main__':
291 unittest.main()