# Copyright 2017 AT&T Intellectual Property. All other rights reserved. # # Licensed under the Apache License, Version 2.0 (the 'License'); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an 'AS IS' BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import json import os import yaml import mock from armada.api.controller import test from armada.common.policies import base as policy_base from armada.exceptions import manifest_exceptions from armada.tests import test_utils from armada.tests.unit.api import base class TestReleasesManifestControllerTest(base.BaseControllerTest): @mock.patch.object(test, 'Manifest') @mock.patch.object(test, 'Tiller') def test_test_controller_with_manifest(self, mock_tiller, mock_manifest): rules = {'armada:tests_manifest': '@'} self.policy.set_rules(rules) manifest_path = os.path.join(os.getcwd(), 'examples', 'keystone-manifest.yaml') with open(manifest_path, 'r') as f: payload = f.read() documents = list(yaml.safe_load_all(payload)) resp = self.app.simulate_post('/api/v1.0/tests', body=payload) self.assertEqual(200, resp.status_code) result = json.loads(resp.text) expected = { "tests": {"passed": [], "skipped": [], "failed": []} } self.assertEqual(expected, result) mock_manifest.assert_called_once_with( documents, target_manifest=None) self.assertTrue(mock_tiller.called) class TestReleasesReleaseNameControllerTest(base.BaseControllerTest): @mock.patch.object(test, 'Tiller') def test_test_controller_test_pass(self, mock_tiller): rules = {'armada:test_release': '@'} self.policy.set_rules(rules) testing_release = mock_tiller.return_value.testing_release testing_release.return_value = mock.Mock( **{'info.status.last_test_suite_run.result': [ mock.Mock(status='PASSED')]}) resp = self.app.simulate_get('/api/v1.0/test/fake-release') self.assertEqual(200, resp.status_code) self.assertEqual('MESSAGE: Test Pass', json.loads(resp.text)['message']) @mock.patch.object(test, 'Tiller') def test_test_controller_test_fail(self, mock_tiller): rules = {'armada:test_release': '@'} self.policy.set_rules(rules) testing_release = mock_tiller.return_value.testing_release testing_release.return_value = mock.Mock( **{'info.status.last_test_suite_run.result': [ mock.Mock(status='FAILED')]}) resp = self.app.simulate_get('/api/v1.0/test/fake-release') self.assertEqual(200, resp.status_code) self.assertEqual('MESSAGE: Test Fail', json.loads(resp.text)['message']) @mock.patch.object(test, 'Tiller') def test_test_controller_no_test_found(self, mock_tiller): rules = {'armada:test_release': '@'} self.policy.set_rules(rules) mock_tiller.return_value.testing_release.return_value = None resp = self.app.simulate_get('/api/v1.0/test/fake-release') self.assertEqual(200, resp.status_code) self.assertEqual('MESSAGE: No test found', json.loads(resp.text)['message']) @test_utils.attr(type=['negative']) class TestReleasesManifestControllerNegativeTest(base.BaseControllerTest): @mock.patch.object(test, 'Manifest') @mock.patch.object(test, 'Tiller') def test_test_controller_tiller_exc_returns_500(self, mock_tiller, _): rules = {'armada:tests_manifest': '@'} self.policy.set_rules(rules) mock_tiller.side_effect = Exception resp = self.app.simulate_post('/api/v1.0/tests') self.assertEqual(500, resp.status_code) @mock.patch.object(test, 'Manifest') @mock.patch.object(test, 'Tiller') def test_test_controller_validation_failure_returns_400( self, *_): rules = {'armada:tests_manifest': '@'} self.policy.set_rules(rules) manifest_path = os.path.join(os.getcwd(), 'examples', 'keystone-manifest.yaml') with open(manifest_path, 'r') as f: payload = f.read() documents = list(yaml.safe_load_all(payload)) documents[0]['schema'] = 'totally-invalid' invalid_payload = yaml.safe_dump_all(documents) resp = self.app.simulate_post('/api/v1.0/tests', body=invalid_payload) self.assertEqual(400, resp.status_code) resp_body = json.loads(resp.text) self.assertEqual(400, resp_body['code']) self.assertEqual(1, resp_body['details']['errorCount']) self.assertIn( {'message': ( 'An error occurred while generating the manifest: Could not ' 'find dependency chart helm-toolkit in armada/Chart/v1.'), 'error': True, 'kind': 'ValidationMessage', 'level': 'Error', 'name': 'ARM001', 'documents': []}, resp_body['details']['messageList']) self.assertEqual(('Failed to validate documents or generate Armada ' 'Manifest from documents.'), resp_body['message']) @mock.patch('armada.utils.validate.Manifest') @mock.patch.object(test, 'Tiller') def test_test_controller_manifest_failure_returns_400( self, _, mock_manifest): rules = {'armada:tests_manifest': '@'} self.policy.set_rules(rules) mock_manifest.return_value.get_manifest.side_effect = ( manifest_exceptions.ManifestException(details='foo')) manifest_path = os.path.join(os.getcwd(), 'examples', 'keystone-manifest.yaml') with open(manifest_path, 'r') as f: payload = f.read() resp = self.app.simulate_post('/api/v1.0/tests', body=payload) self.assertEqual(400, resp.status_code) resp_body = json.loads(resp.text) self.assertEqual(400, resp_body['code']) self.assertEqual(1, resp_body['details']['errorCount']) self.assertEqual( [{'message': ( 'An error occurred while generating the manifest: foo.'), 'error': True, 'kind': 'ValidationMessage', 'level': 'Error', 'name': 'ARM001', 'documents': []}], resp_body['details']['messageList']) self.assertEqual(('Failed to validate documents or generate Armada ' 'Manifest from documents.'), resp_body['message']) @test_utils.attr(type=['negative']) class TestReleasesReleaseNameControllerNegativeTest(base.BaseControllerTest): @mock.patch.object(test, 'Tiller') def test_test_controller_tiller_exc_returns_500(self, mock_tiller): rules = {'armada:test_release': '@'} self.policy.set_rules(rules) mock_tiller.side_effect = Exception resp = self.app.simulate_get('/api/v1.0/test/fake-release') self.assertEqual(500, resp.status_code) class TestReleasesReleaseNameControllerNegativeRbacTest( base.BaseControllerTest): @test_utils.attr(type=['negative']) def test_test_release_insufficient_permissions(self): """Tests the GET /api/v1.0/test/{release} endpoint returns 403 following failed authorization. """ rules = {'armada:test_release': policy_base.RULE_ADMIN_REQUIRED} self.policy.set_rules(rules) resp = self.app.simulate_get('/api/v1.0/test/test-release') self.assertEqual(403, resp.status_code) class TestReleasesManifestControllerNegativeRbacTest(base.BaseControllerTest): @test_utils.attr(type=['negative']) def test_tests_manifest_insufficient_permissions(self): """Tests the POST /api/v1.0/tests endpoint returns 403 following failed authorization. """ rules = {'armada:tests_manifest': policy_base.RULE_ADMIN_REQUIRED} self.policy.set_rules(rules) resp = self.app.simulate_post('/api/v1.0/tests') self.assertEqual(403, resp.status_code)