Bring in aarch64 support in apex
[apex.git] / apex / tests / test_apex_common_builder.py
1 ##############################################################################
2 # Copyright (c) 2017 Tim Rozet (Red Hat)
3 #
4 # All rights reserved. This program and the accompanying materials
5 # are made available under the terms of the Apache License, Version 2.0
6 # which accompanies this distribution, and is available at
7 # http://www.apache.org/licenses/LICENSE-2.0
8 ##############################################################################
9
10 import unittest
11
12 from apex.builders import common_builder as c_builder
13 from apex.builders import exceptions
14 from apex.common import constants as con
15 from mock import patch
16 from mock import mock_open
17 from mock import MagicMock
18
19 DOCKER_YAML = {
20     'resource_registry': {
21         'OS::TripleO::Services::NovaApi': '../docker/services/nova-api.yaml',
22         'OS::TripleO::Services::NovaConductor':
23             '../docker/services/nova-conductor.yaml'
24     }
25 }
26
27 a_mock_open = mock_open(read_data=None)
28
29
30 class TestCommonBuilder(unittest.TestCase):
31     @classmethod
32     def setup_class(cls):
33         """This method is run once for each class before any tests are run"""
34
35     @classmethod
36     def teardown_class(cls):
37         """This method is run once for each class _after_ all tests are run"""
38
39     def setup(self):
40         """This method is run once before _each_ test method is executed"""
41
42     def teardown(self):
43         """This method is run once after _each_ test method is executed"""
44
45     def test_project_to_path(self):
46         project = 'openstack/tripleo-heat-templates'
47         path = '/usr/share/openstack-tripleo-heat-templates'
48         self.assertEquals(c_builder.project_to_path(project), path)
49         project = 'openstack/puppet-tripleo'
50         path = '/etc/puppet/modules/tripleo'
51         self.assertEquals(c_builder.project_to_path(project), path)
52         project = 'openstack/nova'
53         path = '/usr/lib/python2.7/site-packages/'
54         self.assertEquals(c_builder.project_to_path(project), path)
55
56     def test_is_patch_promoted(self):
57         dummy_change = {'submitted': '2017-06-05 20:23:09.000000000',
58                         'status': 'MERGED'}
59         self.assertTrue(c_builder.is_patch_promoted(dummy_change,
60                                                     'master',
61                                                     con.DOCKERHUB_OOO))
62
63     def test_is_patch_promoted_docker(self):
64         dummy_change = {'submitted': '2017-06-05 20:23:09.000000000',
65                         'status': 'MERGED'}
66         dummy_image = 'centos-binary-opendaylight'
67         self.assertTrue(c_builder.is_patch_promoted(dummy_change,
68                                                     'master',
69                                                     con.DOCKERHUB_OOO,
70                                                     docker_image=dummy_image))
71
72     def test_patch_not_promoted(self):
73         dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
74                         'status': 'MERGED'}
75         self.assertFalse(c_builder.is_patch_promoted(dummy_change,
76                                                      'master',
77                                                      con.DOCKERHUB_OOO))
78
79     def test_patch_not_promoted_docker(self):
80         dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
81                         'status': 'MERGED'}
82         dummy_image = 'centos-binary-opendaylight'
83         self.assertFalse(c_builder.is_patch_promoted(dummy_change,
84                                                      'master',
85                                                      con.DOCKERHUB_OOO,
86                                                      docker_image=dummy_image))
87
88     def test_patch_not_promoted_and_not_merged(self):
89         dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
90                         'status': 'BLAH'}
91         self.assertFalse(c_builder.is_patch_promoted(dummy_change,
92                                                      'master',
93                                                      con.DOCKERHUB_OOO))
94
95     @patch('builtins.open', mock_open())
96     @patch('apex.builders.common_builder.is_patch_promoted')
97     @patch('apex.build_utils.get_change')
98     @patch('apex.build_utils.get_patch')
99     @patch('apex.virtual.utils.virt_customize')
100     def test_add_upstream_patches(self, mock_customize, mock_get_patch,
101                                   mock_get_change, mock_is_patch_promoted):
102         mock_get_patch.return_value = None
103         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
104         patches = [{
105             'change-id': change_id,
106             'project': 'openstack/tripleo-heat-templates'
107         }]
108         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/')
109         assert mock_customize.not_called
110         project_path = '/usr/share/openstack-tripleo-heat-templates'
111         patch_file = "{}.patch".format(change_id)
112         patch_file_path = "/dummytmp/{}".format(patch_file)
113         test_virt_ops = [
114             {con.VIRT_INSTALL: 'patch'},
115             {con.VIRT_UPLOAD: "{}:{}".format(patch_file_path,
116                                              project_path)},
117             {con.VIRT_RUN_CMD: "cd {} && patch -p1 < {}".format(
118                 project_path, patch_file)}]
119         mock_get_patch.return_value = 'some random diff'
120         mock_is_patch_promoted.return_value = False
121         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/')
122         mock_customize.assert_called_once_with(test_virt_ops, 'dummy.qcow2')
123
124     @patch('builtins.open', mock_open())
125     @patch('apex.builders.common_builder.is_patch_promoted')
126     @patch('apex.build_utils.get_change')
127     @patch('apex.build_utils.get_patch')
128     @patch('apex.virtual.utils.virt_customize')
129     def test_add_upstream_patches_docker_puppet(
130             self, mock_customize, mock_get_patch, mock_get_change,
131             mock_is_patch_promoted):
132         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
133         patches = [{
134             'change-id': change_id,
135             'project': 'openstack/puppet-tripleo'
136         }]
137         project_path = '/etc/puppet/modules/tripleo'
138         patch_file = "{}.patch".format(change_id)
139         patch_file_path = "/dummytmp/{}".format(patch_file)
140         test_virt_ops = [
141             {con.VIRT_INSTALL: 'patch'},
142             {con.VIRT_UPLOAD: "{}:{}".format(patch_file_path,
143                                              project_path)},
144             {con.VIRT_RUN_CMD: "cd {} && patch -p1 < {}".format(
145                 project_path, patch_file)}]
146         mock_get_patch.return_value = 'some random diff'
147         mock_is_patch_promoted.return_value = False
148         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/',
149                                        uc_ip='192.0.2.1',
150                                        docker_tag='latest')
151         mock_customize.assert_called_once_with(test_virt_ops, 'dummy.qcow2')
152
153     @patch('builtins.open', mock_open())
154     @patch('apex.builders.common_builder.is_patch_promoted')
155     @patch('apex.build_utils.get_change')
156     @patch('apex.builders.common_builder.project_to_docker_image')
157     @patch('apex.builders.overcloud_builder.build_dockerfile')
158     @patch('apex.build_utils.get_patch')
159     @patch('apex.virtual.utils.virt_customize')
160     def test_add_upstream_patches_docker_python(
161             self, mock_customize, mock_get_patch, mock_build_docker_file,
162             mock_project2docker, ock_get_change, mock_is_patch_promoted):
163         mock_project2docker.return_value = ['NovaApi']
164         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
165         patches = [{
166             'change-id': change_id,
167             'project': 'openstack/nova'
168         }]
169         mock_get_patch.return_value = 'some random diff'
170         mock_is_patch_promoted.return_value = False
171         services = c_builder.add_upstream_patches(patches, 'dummy.qcow2',
172                                                   '/dummytmp/',
173                                                   uc_ip='192.0.2.1',
174                                                   docker_tag='latest')
175         assert mock_customize.not_called
176         assert mock_build_docker_file.called
177         self.assertSetEqual(services, {'NovaApi'})
178
179     @patch('builtins.open', mock_open())
180     @patch('apex.builders.common_builder.is_patch_promoted')
181     @patch('apex.build_utils.get_change')
182     @patch('apex.builders.common_builder.project_to_docker_image')
183     @patch('apex.builders.overcloud_builder.build_dockerfile')
184     @patch('apex.build_utils.get_patch')
185     @patch('apex.virtual.utils.virt_customize')
186     def test_not_add_upstream_patches_docker_python(
187             self, mock_customize, mock_get_patch, mock_build_docker_file,
188             mock_project2docker, ock_get_change, mock_is_patch_promoted):
189         # Test that the calls are not made when the patch is already merged and
190         # promoted
191         mock_project2docker.return_value = ['NovaApi']
192         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
193         patches = [{
194             'change-id': change_id,
195             'project': 'openstack/nova'
196         }]
197         mock_get_patch.return_value = 'some random diff'
198         mock_is_patch_promoted.return_value = True
199         services = c_builder.add_upstream_patches(patches, 'dummy.qcow2',
200                                                   '/dummytmp/',
201                                                   uc_ip='192.0.2.1',
202                                                   docker_tag='latest')
203         assert mock_customize.not_called
204         assert mock_build_docker_file.not_called
205         assert len(services) == 0
206
207     @patch('builtins.open', mock_open())
208     @patch('apex.builders.common_builder.is_patch_promoted')
209     @patch('apex.build_utils.get_change')
210     @patch('apex.build_utils.get_patch')
211     @patch('apex.virtual.utils.virt_customize')
212     def test_not_upstream_patches_docker_puppet(
213             self, mock_customize, mock_get_patch, mock_get_change,
214             mock_is_patch_promoted):
215         # Test that the calls are not made when the patch is already merged and
216         # promoted
217         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
218         patches = [{
219             'change-id': change_id,
220             'project': 'openstack/puppet-tripleo'
221         }]
222         mock_get_patch.return_value = 'some random diff'
223         mock_is_patch_promoted.return_value = True
224         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/',
225                                        uc_ip='192.0.2.1',
226                                        docker_tag='latest')
227         assert mock_customize.not_called
228
229     @patch('builtins.open', mock_open())
230     @patch('apex.virtual.utils.virt_customize')
231     def test_add_repo(self, mock_customize):
232         c_builder.add_repo('fake/url', 'dummyrepo', 'dummy.qcow2',
233                            '/dummytmp/')
234         repo_file_path = '/dummytmp/dummyrepo.repo'
235         test_virt_ops = [
236             {con.VIRT_UPLOAD: "{}:/etc/yum.repos.d/".format(repo_file_path)}
237         ]
238         mock_customize.assert_called_once_with(test_virt_ops, 'dummy.qcow2')
239
240     @patch('builtins.open', mock_open())
241     @patch('git.Repo.clone_from')
242     def test_create_git_archive(self, mock_git):
243         mock_git.return_value = MagicMock()
244         self.assertEqual(c_builder.create_git_archive('fake/url', 'dummyrepo',
245                                                       '/dummytmp/'),
246                          '/dummytmp/dummyrepo.tar')
247
248     def test_project_to_docker_image(self):
249         found_services = c_builder.project_to_docker_image('nova',
250                                                            con.DOCKERHUB_OOO)
251         assert 'nova-api' in found_services
252
253     @patch('apex.common.utils.open_webpage')
254     def test_project_to_docker_image_bad_web_content(
255             self, mock_open_web):
256         mock_open_web.return_value = b'{"blah": "blah"}'
257         self.assertRaises(exceptions.ApexCommonBuilderException,
258                           c_builder.project_to_docker_image,
259                           'nova',
260                           con.DOCKERHUB_OOO)
261
262     def test_get_neutron_driver(self):
263         ds_opts = {'dataplane': 'fdio',
264                    'sdn_controller': 'opendaylight',
265                    'odl_version': 'master',
266                    'vpn': False,
267                    'sriov': False}
268         self.assertEquals(c_builder.get_neutron_driver(ds_opts),
269                           'odl')
270         ds_opts['sdn_controller'] = None
271         ds_opts['vpp'] = True
272         self.assertEquals(c_builder.get_neutron_driver(ds_opts),
273                           'vpp')
274         ds_opts['sdn_controller'] = 'ovn'
275         self.assertEquals(c_builder.get_neutron_driver(ds_opts),
276                           'ovn')
277
278     @patch('apex.builders.common_builder.yaml')
279     @patch('apex.overcloud.deploy.os.path.isfile')
280     @patch('builtins.open', a_mock_open, create=True)
281     def test_prepare_container_images(self, mock_is_file, mock_yaml):
282         mock_yaml.safe_load.return_value = {
283             'parameter_defaults': {
284                 'ContainerImagePrepare': [
285                     {'set':
286                         {'namespace': 'blah',
287                          'neutron_driver': 'null',
288                          }
289                      }
290                 ]
291             }
292         }
293         expected_output = {
294             'parameter_defaults': {
295                 'ContainerImagePrepare': [
296                     {'set':
297                         {'namespace': 'docker.io/tripleoqueens',
298                          'neutron_driver': 'odl',
299                          }
300                      }
301                 ]
302             }
303         }
304
305         c_builder.prepare_container_images('dummy.yaml', 'queens',
306                                            'odl')
307         mock_yaml.safe_dump.assert_called_with(
308             expected_output,
309             a_mock_open.return_value,
310             default_flow_style=False)