Fixes deployment failure with allNodesConfig
[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
28 class TestCommonBuilder(unittest.TestCase):
29     @classmethod
30     def setup_class(cls):
31         """This method is run once for each class before any tests are run"""
32
33     @classmethod
34     def teardown_class(cls):
35         """This method is run once for each class _after_ all tests are run"""
36
37     def setup(self):
38         """This method is run once before _each_ test method is executed"""
39
40     def teardown(self):
41         """This method is run once after _each_ test method is executed"""
42
43     def test_project_to_path(self):
44         project = 'openstack/tripleo-heat-templates'
45         path = '/usr/share/openstack-tripleo-heat-templates'
46         self.assertEquals(c_builder.project_to_path(project), path)
47         project = 'openstack/puppet-tripleo'
48         path = '/etc/puppet/modules/tripleo'
49         self.assertEquals(c_builder.project_to_path(project), path)
50         project = 'openstack/nova'
51         path = '/usr/lib/python2.7/site-packages/'
52         self.assertEquals(c_builder.project_to_path(project), path)
53
54     def test_is_patch_promoted(self):
55         dummy_change = {'submitted': '2017-06-05 20:23:09.000000000',
56                         'status': 'MERGED'}
57         self.assertTrue(c_builder.is_patch_promoted(dummy_change,
58                                                     'master'))
59
60     def test_is_patch_promoted_docker(self):
61         dummy_change = {'submitted': '2017-06-05 20:23:09.000000000',
62                         'status': 'MERGED'}
63         dummy_image = 'centos-binary-opendaylight'
64         self.assertTrue(c_builder.is_patch_promoted(dummy_change,
65                                                     'master',
66                                                     docker_image=dummy_image))
67
68     def test_patch_not_promoted(self):
69         dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
70                         'status': 'MERGED'}
71         self.assertFalse(c_builder.is_patch_promoted(dummy_change,
72                                                      'master'))
73
74     def test_patch_not_promoted_docker(self):
75         dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
76                         'status': 'MERGED'}
77         dummy_image = 'centos-binary-opendaylight'
78         self.assertFalse(c_builder.is_patch_promoted(dummy_change,
79                                                      'master',
80                                                      docker_image=dummy_image))
81
82     def test_patch_not_promoted_and_not_merged(self):
83         dummy_change = {'submitted': '2900-06-05 20:23:09.000000000',
84                         'status': 'BLAH'}
85         self.assertFalse(c_builder.is_patch_promoted(dummy_change,
86                                                      'master'))
87
88     @patch('builtins.open', mock_open())
89     @patch('apex.builders.common_builder.is_patch_promoted')
90     @patch('apex.build_utils.get_change')
91     @patch('apex.build_utils.get_patch')
92     @patch('apex.virtual.utils.virt_customize')
93     def test_add_upstream_patches(self, mock_customize, mock_get_patch,
94                                   mock_get_change, mock_is_patch_promoted):
95         mock_get_patch.return_value = None
96         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
97         patches = [{
98             'change-id': change_id,
99             'project': 'openstack/tripleo-heat-templates'
100         }]
101         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/')
102         assert mock_customize.not_called
103         project_path = '/usr/share/openstack-tripleo-heat-templates'
104         patch_file = "{}.patch".format(change_id)
105         patch_file_path = "/dummytmp/{}".format(patch_file)
106         test_virt_ops = [
107             {con.VIRT_INSTALL: 'patch'},
108             {con.VIRT_UPLOAD: "{}:{}".format(patch_file_path,
109                                              project_path)},
110             {con.VIRT_RUN_CMD: "cd {} && patch -p1 < {}".format(
111                 project_path, patch_file)}]
112         mock_get_patch.return_value = 'some random diff'
113         mock_is_patch_promoted.return_value = False
114         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/')
115         mock_customize.assert_called_once_with(test_virt_ops, 'dummy.qcow2')
116
117     @patch('builtins.open', mock_open())
118     @patch('apex.builders.common_builder.is_patch_promoted')
119     @patch('apex.build_utils.get_change')
120     @patch('apex.build_utils.get_patch')
121     @patch('apex.virtual.utils.virt_customize')
122     def test_add_upstream_patches_docker_puppet(
123             self, mock_customize, mock_get_patch, mock_get_change,
124             mock_is_patch_promoted):
125         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
126         patches = [{
127             'change-id': change_id,
128             'project': 'openstack/puppet-tripleo'
129         }]
130         project_path = '/etc/puppet/modules/tripleo'
131         patch_file = "{}.patch".format(change_id)
132         patch_file_path = "/dummytmp/{}".format(patch_file)
133         test_virt_ops = [
134             {con.VIRT_INSTALL: 'patch'},
135             {con.VIRT_UPLOAD: "{}:{}".format(patch_file_path,
136                                              project_path)},
137             {con.VIRT_RUN_CMD: "cd {} && patch -p1 < {}".format(
138                 project_path, patch_file)}]
139         mock_get_patch.return_value = 'some random diff'
140         mock_is_patch_promoted.return_value = False
141         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/',
142                                        uc_ip='192.0.2.1',
143                                        docker_tag='latest')
144         mock_customize.assert_called_once_with(test_virt_ops, 'dummy.qcow2')
145
146     @patch('builtins.open', mock_open())
147     @patch('apex.builders.common_builder.is_patch_promoted')
148     @patch('apex.build_utils.get_change')
149     @patch('apex.builders.common_builder.project_to_docker_image')
150     @patch('apex.builders.overcloud_builder.build_dockerfile')
151     @patch('apex.build_utils.get_patch')
152     @patch('apex.virtual.utils.virt_customize')
153     def test_add_upstream_patches_docker_python(
154             self, mock_customize, mock_get_patch, mock_build_docker_file,
155             mock_project2docker, ock_get_change, mock_is_patch_promoted):
156         mock_project2docker.return_value = ['NovaApi']
157         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
158         patches = [{
159             'change-id': change_id,
160             'project': 'openstack/nova'
161         }]
162         mock_get_patch.return_value = 'some random diff'
163         mock_is_patch_promoted.return_value = False
164         services = c_builder.add_upstream_patches(patches, 'dummy.qcow2',
165                                                   '/dummytmp/',
166                                                   uc_ip='192.0.2.1',
167                                                   docker_tag='latest')
168         assert mock_customize.not_called
169         assert mock_build_docker_file.called
170         self.assertSetEqual(services, {'NovaApi'})
171
172     @patch('builtins.open', mock_open())
173     @patch('apex.builders.common_builder.is_patch_promoted')
174     @patch('apex.build_utils.get_change')
175     @patch('apex.builders.common_builder.project_to_docker_image')
176     @patch('apex.builders.overcloud_builder.build_dockerfile')
177     @patch('apex.build_utils.get_patch')
178     @patch('apex.virtual.utils.virt_customize')
179     def test_not_add_upstream_patches_docker_python(
180             self, mock_customize, mock_get_patch, mock_build_docker_file,
181             mock_project2docker, ock_get_change, mock_is_patch_promoted):
182         # Test that the calls are not made when the patch is already merged and
183         # promoted
184         mock_project2docker.return_value = ['NovaApi']
185         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
186         patches = [{
187             'change-id': change_id,
188             'project': 'openstack/nova'
189         }]
190         mock_get_patch.return_value = 'some random diff'
191         mock_is_patch_promoted.return_value = True
192         services = c_builder.add_upstream_patches(patches, 'dummy.qcow2',
193                                                   '/dummytmp/',
194                                                   uc_ip='192.0.2.1',
195                                                   docker_tag='latest')
196         assert mock_customize.not_called
197         assert mock_build_docker_file.not_called
198         assert len(services) == 0
199
200     @patch('builtins.open', mock_open())
201     @patch('apex.builders.common_builder.is_patch_promoted')
202     @patch('apex.build_utils.get_change')
203     @patch('apex.build_utils.get_patch')
204     @patch('apex.virtual.utils.virt_customize')
205     def test_not_upstream_patches_docker_puppet(
206             self, mock_customize, mock_get_patch, mock_get_change,
207             mock_is_patch_promoted):
208         # Test that the calls are not made when the patch is already merged and
209         # promoted
210         change_id = 'I301370fbf47a71291614dd60e4c64adc7b5ebb42'
211         patches = [{
212             'change-id': change_id,
213             'project': 'openstack/puppet-tripleo'
214         }]
215         mock_get_patch.return_value = 'some random diff'
216         mock_is_patch_promoted.return_value = True
217         c_builder.add_upstream_patches(patches, 'dummy.qcow2', '/dummytmp/',
218                                        uc_ip='192.0.2.1',
219                                        docker_tag='latest')
220         assert mock_customize.not_called
221
222     @patch('builtins.open', mock_open())
223     @patch('apex.virtual.utils.virt_customize')
224     def test_add_repo(self, mock_customize):
225         c_builder.add_repo('fake/url', 'dummyrepo', 'dummy.qcow2',
226                            '/dummytmp/')
227         repo_file_path = '/dummytmp/dummyrepo.repo'
228         test_virt_ops = [
229             {con.VIRT_UPLOAD: "{}:/etc/yum.repos.d/".format(repo_file_path)}
230         ]
231         mock_customize.assert_called_once_with(test_virt_ops, 'dummy.qcow2')
232
233     @patch('builtins.open', mock_open())
234     @patch('git.Repo.clone_from')
235     def test_create_git_archive(self, mock_git):
236         mock_git.return_value = MagicMock()
237         self.assertEqual(c_builder.create_git_archive('fake/url', 'dummyrepo',
238                                                       '/dummytmp/'),
239                          '/dummytmp/dummyrepo.tar')
240
241     def test_project_to_docker_image(self):
242         found_services = c_builder.project_to_docker_image(project='nova')
243         assert 'nova-api' in found_services
244
245     @patch('apex.common.utils.open_webpage')
246     def test_project_to_docker_image_bad_web_content(
247             self, mock_open_web):
248         mock_open_web.return_value = b'{"blah": "blah"}'
249         self.assertRaises(exceptions.ApexCommonBuilderException,
250                           c_builder.project_to_docker_image,
251                           'nova')