dede55a2f85774f35cc11ed4275291295624e2a0
[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
62     def test_is_patch_promoted_docker(self):
63         dummy_change = {'submitted': '2017-06-05 20:23:09.000000000',
64                         'status': 'MERGED'}
65         dummy_image = 'centos-binary-opendaylight'
66         self.assertTrue(c_builder.is_patch_promoted(dummy_change,
67                                                     'master',
68                                                     docker_image=dummy_image))
69
70     def test_patch_not_promoted(self):
71         dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
72                         'status': 'MERGED'}
73         self.assertFalse(c_builder.is_patch_promoted(dummy_change,
74                                                      'master'))
75
76     def test_patch_not_promoted_docker(self):
77         dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
78                         'status': 'MERGED'}
79         dummy_image = 'centos-binary-opendaylight'
80         self.assertFalse(c_builder.is_patch_promoted(dummy_change,
81                                                      'master',
82                                                      docker_image=dummy_image))
83
84     def test_patch_not_promoted_and_not_merged(self):
85         dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
86                         'status': 'BLAH'}
87         self.assertFalse(c_builder.is_patch_promoted(dummy_change,
88                                                      'master'))
89
90     @patch('builtins.open', mock_open())
91     @patch('apex.builders.common_builder.is_patch_promoted')
92     @patch('apex.build_utils.get_change')
93     @patch('apex.build_utils.get_patch')
94     @patch('apex.virtual.utils.virt_customize')
95     def test_add_upstream_patches(self, mock_customize, mock_get_patch,
96                                   mock_get_change, mock_is_patch_promoted):
97         mock_get_patch.return_value = None
98         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
99         patches = [{
100             'change-id': change_id,
101             'project': 'openstack/tripleo-heat-templates'
102         }]
103         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/')
104         assert mock_customize.not_called
105         project_path = '/usr/share/openstack-tripleo-heat-templates'
106         patch_file = "{}.patch".format(change_id)
107         patch_file_path = "/dummytmp/{}".format(patch_file)
108         test_virt_ops = [
109             {con.VIRT_INSTALL: 'patch'},
110             {con.VIRT_UPLOAD: "{}:{}".format(patch_file_path,
111                                              project_path)},
112             {con.VIRT_RUN_CMD: "cd {} && patch -p1 < {}".format(
113                 project_path, patch_file)}]
114         mock_get_patch.return_value = 'some random diff'
115         mock_is_patch_promoted.return_value = False
116         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/')
117         mock_customize.assert_called_once_with(test_virt_ops, 'dummy.qcow2')
118
119     @patch('builtins.open', mock_open())
120     @patch('apex.builders.common_builder.is_patch_promoted')
121     @patch('apex.build_utils.get_change')
122     @patch('apex.build_utils.get_patch')
123     @patch('apex.virtual.utils.virt_customize')
124     def test_add_upstream_patches_docker_puppet(
125             self, mock_customize, mock_get_patch, mock_get_change,
126             mock_is_patch_promoted):
127         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
128         patches = [{
129             'change-id': change_id,
130             'project': 'openstack/puppet-tripleo'
131         }]
132         project_path = '/etc/puppet/modules/tripleo'
133         patch_file = "{}.patch".format(change_id)
134         patch_file_path = "/dummytmp/{}".format(patch_file)
135         test_virt_ops = [
136             {con.VIRT_INSTALL: 'patch'},
137             {con.VIRT_UPLOAD: "{}:{}".format(patch_file_path,
138                                              project_path)},
139             {con.VIRT_RUN_CMD: "cd {} && patch -p1 < {}".format(
140                 project_path, patch_file)}]
141         mock_get_patch.return_value = 'some random diff'
142         mock_is_patch_promoted.return_value = False
143         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/',
144                                        uc_ip='192.0.2.1',
145                                        docker_tag='latest')
146         mock_customize.assert_called_once_with(test_virt_ops, 'dummy.qcow2')
147
148     @patch('builtins.open', mock_open())
149     @patch('apex.builders.common_builder.is_patch_promoted')
150     @patch('apex.build_utils.get_change')
151     @patch('apex.builders.common_builder.project_to_docker_image')
152     @patch('apex.builders.overcloud_builder.build_dockerfile')
153     @patch('apex.build_utils.get_patch')
154     @patch('apex.virtual.utils.virt_customize')
155     def test_add_upstream_patches_docker_python(
156             self, mock_customize, mock_get_patch, mock_build_docker_file,
157             mock_project2docker, ock_get_change, mock_is_patch_promoted):
158         mock_project2docker.return_value = ['NovaApi']
159         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
160         patches = [{
161             'change-id': change_id,
162             'project': 'openstack/nova'
163         }]
164         mock_get_patch.return_value = 'some random diff'
165         mock_is_patch_promoted.return_value = False
166         services = c_builder.add_upstream_patches(patches, 'dummy.qcow2',
167                                                   '/dummytmp/',
168                                                   uc_ip='192.0.2.1',
169                                                   docker_tag='latest')
170         assert mock_customize.not_called
171         assert mock_build_docker_file.called
172         self.assertSetEqual(services, {'NovaApi'})
173
174     @patch('builtins.open', mock_open())
175     @patch('apex.builders.common_builder.is_patch_promoted')
176     @patch('apex.build_utils.get_change')
177     @patch('apex.builders.common_builder.project_to_docker_image')
178     @patch('apex.builders.overcloud_builder.build_dockerfile')
179     @patch('apex.build_utils.get_patch')
180     @patch('apex.virtual.utils.virt_customize')
181     def test_not_add_upstream_patches_docker_python(
182             self, mock_customize, mock_get_patch, mock_build_docker_file,
183             mock_project2docker, ock_get_change, mock_is_patch_promoted):
184         # Test that the calls are not made when the patch is already merged and
185         # promoted
186         mock_project2docker.return_value = ['NovaApi']
187         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
188         patches = [{
189             'change-id': change_id,
190             'project': 'openstack/nova'
191         }]
192         mock_get_patch.return_value = 'some random diff'
193         mock_is_patch_promoted.return_value = True
194         services = c_builder.add_upstream_patches(patches, 'dummy.qcow2',
195                                                   '/dummytmp/',
196                                                   uc_ip='192.0.2.1',
197                                                   docker_tag='latest')
198         assert mock_customize.not_called
199         assert mock_build_docker_file.not_called
200         assert len(services) == 0
201
202     @patch('builtins.open', mock_open())
203     @patch('apex.builders.common_builder.is_patch_promoted')
204     @patch('apex.build_utils.get_change')
205     @patch('apex.build_utils.get_patch')
206     @patch('apex.virtual.utils.virt_customize')
207     def test_not_upstream_patches_docker_puppet(
208             self, mock_customize, mock_get_patch, mock_get_change,
209             mock_is_patch_promoted):
210         # Test that the calls are not made when the patch is already merged and
211         # promoted
212         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
213         patches = [{
214             'change-id': change_id,
215             'project': 'openstack/puppet-tripleo'
216         }]
217         mock_get_patch.return_value = 'some random diff'
218         mock_is_patch_promoted.return_value = True
219         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/',
220                                        uc_ip='192.0.2.1',
221                                        docker_tag='latest')
222         assert mock_customize.not_called
223
224     @patch('builtins.open', mock_open())
225     @patch('apex.virtual.utils.virt_customize')
226     def test_add_repo(self, mock_customize):
227         c_builder.add_repo('fake/url', 'dummyrepo', 'dummy.qcow2',
228                            '/dummytmp/')
229         repo_file_path = '/dummytmp/dummyrepo.repo'
230         test_virt_ops = [
231             {con.VIRT_UPLOAD: "{}:/etc/yum.repos.d/".format(repo_file_path)}
232         ]
233         mock_customize.assert_called_once_with(test_virt_ops, 'dummy.qcow2')
234
235     @patch('builtins.open', mock_open())
236     @patch('git.Repo.clone_from')
237     def test_create_git_archive(self, mock_git):
238         mock_git.return_value = MagicMock()
239         self.assertEqual(c_builder.create_git_archive('fake/url', 'dummyrepo',
240                                                       '/dummytmp/'),
241                          '/dummytmp/dummyrepo.tar')
242
243     def test_project_to_docker_image(self):
244         found_services = c_builder.project_to_docker_image(project='nova')
245         assert 'nova-api' in found_services
246
247     @patch('apex.common.utils.open_webpage')
248     def test_project_to_docker_image_bad_web_content(
249             self, mock_open_web):
250         mock_open_web.return_value = b'{"blah": "blah"}'
251         self.assertRaises(exceptions.ApexCommonBuilderException,
252                           c_builder.project_to_docker_image,
253                           'nova')
254
255     def test_get_neutron_driver(self):
256         ds_opts = {'dataplane': 'fdio',
257                    'sdn_controller': 'opendaylight',
258                    'odl_version': 'master',
259                    'vpn': False,
260                    'sriov': False}
261         self.assertEquals(c_builder.get_neutron_driver(ds_opts),
262                           'opendaylight')
263         ds_opts['sdn_controller'] = None
264         ds_opts['vpp'] = True
265         self.assertEquals(c_builder.get_neutron_driver(ds_opts),
266                           'vpp')
267         ds_opts['sdn_controller'] = 'ovn'
268         self.assertEquals(c_builder.get_neutron_driver(ds_opts),
269                           'ovn')
270
271     @patch('apex.builders.common_builder.yaml')
272     @patch('apex.overcloud.deploy.os.path.isfile')
273     @patch('builtins.open', a_mock_open, create=True)
274     def test_prepare_container_images(self, mock_is_file, mock_yaml):
275         mock_yaml.safe_load.return_value = {
276             'parameter_defaults': {
277                 'ContainerImagePrepare': [
278                     {'set':
279                         {'namespace': 'blah',
280                          'neutron_driver': 'null',
281                          }
282                      }
283                 ]
284             }
285         }
286         expected_output = {
287             'parameter_defaults': {
288                 'ContainerImagePrepare': [
289                     {'set':
290                         {'namespace': 'docker.io/tripleoqueens',
291                          'neutron_driver': 'opendaylight',
292                          }
293                      }
294                 ]
295             }
296         }
297
298         c_builder.prepare_container_images('dummy.yaml', 'queens',
299                                            'opendaylight')
300         mock_yaml.safe_dump.assert_called_with(
301             expected_output,
302             a_mock_open.return_value,
303             default_flow_style=False)