Blame tests/unittests/test_handler/test_schema.py

Packit Service a04d08
# This file is part of cloud-init. See LICENSE file for license information.
Packit Service 11b429
Packit Service a04d08
from cloudinit.config.schema import (
Packit Service a04d08
    CLOUD_CONFIG_HEADER, SchemaValidationError, annotated_cloudconfig_file,
Packit Service a04d08
    get_schema_doc, get_schema, validate_cloudconfig_file,
Packit Service a04d08
    validate_cloudconfig_schema, main)
Packit Service a04d08
from cloudinit.util import write_file
Packit Service a04d08
Packit Service a04d08
from cloudinit.tests.helpers import CiTestCase, mock, skipUnlessJsonSchema
Packit Service a04d08
Packit Service a04d08
from copy import copy
Packit Service a04d08
import os
Packit Service 11b429
from six import StringIO
Packit Service a04d08
from textwrap import dedent
Packit Service a04d08
from yaml import safe_load
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class GetSchemaTest(CiTestCase):
Packit Service a04d08
Packit Service a04d08
    def test_get_schema_coalesces_known_schema(self):
Packit Service a04d08
        """Every cloudconfig module with schema is listed in allOf keyword."""
Packit Service a04d08
        schema = get_schema()
Packit Service 11b429
        self.assertItemsEqual(
Packit Service a04d08
            [
Packit Service a04d08
                'cc_bootcmd',
Packit Service a04d08
                'cc_ntp',
Packit Service a04d08
                'cc_resizefs',
Packit Service a04d08
                'cc_runcmd',
Packit Service a04d08
                'cc_snap',
Packit Service a04d08
                'cc_ubuntu_advantage',
Packit Service a04d08
                'cc_ubuntu_drivers',
Packit Service 11b429
                'cc_zypper_add_repo'
Packit Service a04d08
            ],
Packit Service a04d08
            [subschema['id'] for subschema in schema['allOf']])
Packit Service a04d08
        self.assertEqual('cloud-config-schema', schema['id'])
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'http://json-schema.org/draft-04/schema#',
Packit Service a04d08
            schema['$schema'])
Packit Service a04d08
        # FULL_SCHEMA is updated by the get_schema call
Packit Service a04d08
        from cloudinit.config.schema import FULL_SCHEMA
Packit Service 11b429
        self.assertItemsEqual(['id', '$schema', 'allOf'], FULL_SCHEMA.keys())
Packit Service a04d08
Packit Service a04d08
    def test_get_schema_returns_global_when_set(self):
Packit Service a04d08
        """When FULL_SCHEMA global is already set, get_schema returns it."""
Packit Service a04d08
        m_schema_path = 'cloudinit.config.schema.FULL_SCHEMA'
Packit Service a04d08
        with mock.patch(m_schema_path, {'here': 'iam'}):
Packit Service a04d08
            self.assertEqual({'here': 'iam'}, get_schema())
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class SchemaValidationErrorTest(CiTestCase):
Packit Service a04d08
    """Test validate_cloudconfig_schema"""
Packit Service a04d08
Packit Service a04d08
    def test_schema_validation_error_expects_schema_errors(self):
Packit Service a04d08
        """SchemaValidationError is initialized from schema_errors."""
Packit Service a04d08
        errors = (('key.path', 'unexpected key "junk"'),
Packit Service a04d08
                  ('key2.path', '"-123" is not a valid "hostname" format'))
Packit Service a04d08
        exception = SchemaValidationError(schema_errors=errors)
Packit Service a04d08
        self.assertIsInstance(exception, Exception)
Packit Service a04d08
        self.assertEqual(exception.schema_errors, errors)
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'Cloud config schema errors: key.path: unexpected key "junk", '
Packit Service a04d08
            'key2.path: "-123" is not a valid "hostname" format',
Packit Service a04d08
            str(exception))
Packit Service a04d08
        self.assertTrue(isinstance(exception, ValueError))
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class ValidateCloudConfigSchemaTest(CiTestCase):
Packit Service a04d08
    """Tests for validate_cloudconfig_schema."""
Packit Service a04d08
Packit Service a04d08
    with_logs = True
Packit Service a04d08
Packit Service a04d08
    @skipUnlessJsonSchema()
Packit Service a04d08
    def test_validateconfig_schema_non_strict_emits_warnings(self):
Packit Service a04d08
        """When strict is False validate_cloudconfig_schema emits warnings."""
Packit Service a04d08
        schema = {'properties': {'p1': {'type': 'string'}}}
Packit Service a04d08
        validate_cloudconfig_schema({'p1': -1}, schema, strict=False)
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            "Invalid config:\np1: -1 is not of type 'string'\n",
Packit Service a04d08
            self.logs.getvalue())
Packit Service a04d08
Packit Service a04d08
    @skipUnlessJsonSchema()
Packit Service a04d08
    def test_validateconfig_schema_emits_warning_on_missing_jsonschema(self):
Packit Service a04d08
        """Warning from validate_cloudconfig_schema when missing jsonschema."""
Packit Service a04d08
        schema = {'properties': {'p1': {'type': 'string'}}}
Packit Service a04d08
        with mock.patch.dict('sys.modules', **{'jsonschema': ImportError()}):
Packit Service a04d08
            validate_cloudconfig_schema({'p1': -1}, schema, strict=True)
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            'Ignoring schema validation. python-jsonschema is not present',
Packit Service a04d08
            self.logs.getvalue())
Packit Service a04d08
Packit Service a04d08
    @skipUnlessJsonSchema()
Packit Service a04d08
    def test_validateconfig_schema_strict_raises_errors(self):
Packit Service a04d08
        """When strict is True validate_cloudconfig_schema raises errors."""
Packit Service a04d08
        schema = {'properties': {'p1': {'type': 'string'}}}
Packit Service a04d08
        with self.assertRaises(SchemaValidationError) as context_mgr:
Packit Service a04d08
            validate_cloudconfig_schema({'p1': -1}, schema, strict=True)
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            "Cloud config schema errors: p1: -1 is not of type 'string'",
Packit Service a04d08
            str(context_mgr.exception))
Packit Service a04d08
Packit Service a04d08
    @skipUnlessJsonSchema()
Packit Service a04d08
    def test_validateconfig_schema_honors_formats(self):
Packit Service a04d08
        """With strict True, validate_cloudconfig_schema errors on format."""
Packit Service a04d08
        schema = {
Packit Service a04d08
            'properties': {'p1': {'type': 'string', 'format': 'hostname'}}}
Packit Service a04d08
        with self.assertRaises(SchemaValidationError) as context_mgr:
Packit Service a04d08
            validate_cloudconfig_schema({'p1': '-1'}, schema, strict=True)
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            "Cloud config schema errors: p1: '-1' is not a 'hostname'",
Packit Service a04d08
            str(context_mgr.exception))
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class ValidateCloudConfigFileTest(CiTestCase):
Packit Service a04d08
    """Tests for validate_cloudconfig_file."""
Packit Service a04d08
Packit Service a04d08
    def setUp(self):
Packit Service a04d08
        super(ValidateCloudConfigFileTest, self).setUp()
Packit Service a04d08
        self.config_file = self.tmp_path('cloudcfg.yaml')
Packit Service a04d08
Packit Service a04d08
    def test_validateconfig_file_error_on_absent_file(self):
Packit Service a04d08
        """On absent config_path, validate_cloudconfig_file errors."""
Packit Service a04d08
        with self.assertRaises(RuntimeError) as context_mgr:
Packit Service a04d08
            validate_cloudconfig_file('/not/here', {})
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'Configfile /not/here does not exist',
Packit Service a04d08
            str(context_mgr.exception))
Packit Service a04d08
Packit Service a04d08
    def test_validateconfig_file_error_on_invalid_header(self):
Packit Service a04d08
        """On invalid header, validate_cloudconfig_file errors.
Packit Service a04d08
Packit Service a04d08
        A SchemaValidationError is raised when the file doesn't begin with
Packit Service a04d08
        CLOUD_CONFIG_HEADER.
Packit Service a04d08
        """
Packit Service a04d08
        write_file(self.config_file, '#junk')
Packit Service a04d08
        with self.assertRaises(SchemaValidationError) as context_mgr:
Packit Service a04d08
            validate_cloudconfig_file(self.config_file, {})
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'Cloud config schema errors: format-l1.c1: File {0} needs to begin'
Packit Service a04d08
            ' with "{1}"'.format(
Packit Service a04d08
                self.config_file, CLOUD_CONFIG_HEADER.decode()),
Packit Service a04d08
            str(context_mgr.exception))
Packit Service a04d08
Packit Service a04d08
    def test_validateconfig_file_error_on_non_yaml_scanner_error(self):
Packit Service a04d08
        """On non-yaml scan issues, validate_cloudconfig_file errors."""
Packit Service a04d08
        # Generate a scanner error by providing text on a single line with
Packit Service a04d08
        # improper indent.
Packit Service a04d08
        write_file(self.config_file, '#cloud-config\nasdf:\nasdf')
Packit Service a04d08
        with self.assertRaises(SchemaValidationError) as context_mgr:
Packit Service a04d08
            validate_cloudconfig_file(self.config_file, {})
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            'schema errors: format-l3.c1: File {0} is not valid yaml.'.format(
Packit Service a04d08
                self.config_file),
Packit Service a04d08
            str(context_mgr.exception))
Packit Service a04d08
Packit Service a04d08
    def test_validateconfig_file_error_on_non_yaml_parser_error(self):
Packit Service a04d08
        """On non-yaml parser issues, validate_cloudconfig_file errors."""
Packit Service a04d08
        write_file(self.config_file, '#cloud-config\n{}}')
Packit Service a04d08
        with self.assertRaises(SchemaValidationError) as context_mgr:
Packit Service a04d08
            validate_cloudconfig_file(self.config_file, {})
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            'schema errors: format-l2.c3: File {0} is not valid yaml.'.format(
Packit Service a04d08
                self.config_file),
Packit Service a04d08
            str(context_mgr.exception))
Packit Service a04d08
Packit Service a04d08
    @skipUnlessJsonSchema()
Packit Service a04d08
    def test_validateconfig_file_sctrictly_validates_schema(self):
Packit Service a04d08
        """validate_cloudconfig_file raises errors on invalid schema."""
Packit Service a04d08
        schema = {
Packit Service a04d08
            'properties': {'p1': {'type': 'string', 'format': 'hostname'}}}
Packit Service a04d08
        write_file(self.config_file, '#cloud-config\np1: "-1"')
Packit Service a04d08
        with self.assertRaises(SchemaValidationError) as context_mgr:
Packit Service a04d08
            validate_cloudconfig_file(self.config_file, schema)
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            "Cloud config schema errors: p1: '-1' is not a 'hostname'",
Packit Service a04d08
            str(context_mgr.exception))
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class GetSchemaDocTest(CiTestCase):
Packit Service a04d08
    """Tests for get_schema_doc."""
Packit Service a04d08
Packit Service a04d08
    def setUp(self):
Packit Service a04d08
        super(GetSchemaDocTest, self).setUp()
Packit Service a04d08
        self.required_schema = {
Packit Service a04d08
            'title': 'title', 'description': 'description', 'id': 'id',
Packit Service a04d08
            'name': 'name', 'frequency': 'frequency',
Packit Service a04d08
            'distros': ['debian', 'rhel']}
Packit Service a04d08
Packit Service a04d08
    def test_get_schema_doc_returns_restructured_text(self):
Packit Service a04d08
        """get_schema_doc returns restructured text for a cloudinit schema."""
Packit Service a04d08
        full_schema = copy(self.required_schema)
Packit Service a04d08
        full_schema.update(
Packit Service a04d08
            {'properties': {
Packit Service a04d08
                'prop1': {'type': 'array', 'description': 'prop-description',
Packit Service a04d08
                          'items': {'type': 'integer'}}}})
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            dedent("""
Packit Service a04d08
                name
Packit Service a04d08
                ----
Packit Service a04d08
                **Summary:** title
Packit Service a04d08
Packit Service a04d08
                description
Packit Service a04d08
Packit Service a04d08
                **Internal name:** ``id``
Packit Service a04d08
Packit Service a04d08
                **Module frequency:** frequency
Packit Service a04d08
Packit Service a04d08
                **Supported distros:** debian, rhel
Packit Service a04d08
Packit Service a04d08
                **Config schema**:
Packit Service a04d08
                    **prop1:** (array of integer) prop-description\n\n"""),
Packit Service a04d08
            get_schema_doc(full_schema))
Packit Service a04d08
Packit Service a04d08
    def test_get_schema_doc_handles_multiple_types(self):
Packit Service a04d08
        """get_schema_doc delimits multiple property types with a '/'."""
Packit Service a04d08
        full_schema = copy(self.required_schema)
Packit Service a04d08
        full_schema.update(
Packit Service a04d08
            {'properties': {
Packit Service a04d08
                'prop1': {'type': ['string', 'integer'],
Packit Service a04d08
                          'description': 'prop-description'}}})
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            '**prop1:** (string/integer) prop-description',
Packit Service a04d08
            get_schema_doc(full_schema))
Packit Service a04d08
Packit Service a04d08
    def test_get_schema_doc_handles_enum_types(self):
Packit Service a04d08
        """get_schema_doc converts enum types to yaml and delimits with '/'."""
Packit Service a04d08
        full_schema = copy(self.required_schema)
Packit Service a04d08
        full_schema.update(
Packit Service a04d08
            {'properties': {
Packit Service a04d08
                'prop1': {'enum': [True, False, 'stuff'],
Packit Service a04d08
                          'description': 'prop-description'}}})
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            '**prop1:** (true/false/stuff) prop-description',
Packit Service a04d08
            get_schema_doc(full_schema))
Packit Service a04d08
Packit Service a04d08
    def test_get_schema_doc_handles_nested_oneof_property_types(self):
Packit Service a04d08
        """get_schema_doc describes array items oneOf declarations in type."""
Packit Service a04d08
        full_schema = copy(self.required_schema)
Packit Service a04d08
        full_schema.update(
Packit Service a04d08
            {'properties': {
Packit Service a04d08
                'prop1': {'type': 'array',
Packit Service a04d08
                          'items': {
Packit Service a04d08
                              'oneOf': [{'type': 'string'},
Packit Service a04d08
                                        {'type': 'integer'}]},
Packit Service a04d08
                          'description': 'prop-description'}}})
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            '**prop1:** (array of (string)/(integer)) prop-description',
Packit Service a04d08
            get_schema_doc(full_schema))
Packit Service a04d08
Packit Service a04d08
    def test_get_schema_doc_handles_string_examples(self):
Packit Service a04d08
        """get_schema_doc properly indented examples as a list of strings."""
Packit Service a04d08
        full_schema = copy(self.required_schema)
Packit Service a04d08
        full_schema.update(
Packit Service a04d08
            {'examples': ['ex1:\n    [don\'t, expand, "this"]', 'ex2: true'],
Packit Service a04d08
             'properties': {
Packit Service a04d08
                'prop1': {'type': 'array', 'description': 'prop-description',
Packit Service a04d08
                          'items': {'type': 'integer'}}}})
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            dedent("""
Packit Service a04d08
                **Config schema**:
Packit Service a04d08
                    **prop1:** (array of integer) prop-description
Packit Service a04d08
Packit Service a04d08
                **Examples**::
Packit Service a04d08
Packit Service a04d08
                    ex1:
Packit Service a04d08
                        [don't, expand, "this"]
Packit Service a04d08
                    # --- Example2 ---
Packit Service a04d08
                    ex2: true
Packit Service a04d08
            """),
Packit Service a04d08
            get_schema_doc(full_schema))
Packit Service a04d08
Packit Service a04d08
    def test_get_schema_doc_raises_key_errors(self):
Packit Service a04d08
        """get_schema_doc raises KeyErrors on missing keys."""
Packit Service a04d08
        for key in self.required_schema:
Packit Service a04d08
            invalid_schema = copy(self.required_schema)
Packit Service a04d08
            invalid_schema.pop(key)
Packit Service a04d08
            with self.assertRaises(KeyError) as context_mgr:
Packit Service a04d08
                get_schema_doc(invalid_schema)
Packit Service a04d08
            self.assertIn(key, str(context_mgr.exception))
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class AnnotatedCloudconfigFileTest(CiTestCase):
Packit Service a04d08
    maxDiff = None
Packit Service a04d08
Packit Service a04d08
    def test_annotated_cloudconfig_file_no_schema_errors(self):
Packit Service a04d08
        """With no schema_errors, print the original content."""
Packit Service a04d08
        content = b'ntp:\n  pools: [ntp1.pools.com]\n'
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            content,
Packit Service a04d08
            annotated_cloudconfig_file({}, content, schema_errors=[]))
Packit Service a04d08
Packit Service a04d08
    def test_annotated_cloudconfig_file_schema_annotates_and_adds_footer(self):
Packit Service a04d08
        """With schema_errors, error lines are annotated and a footer added."""
Packit Service a04d08
        content = dedent("""\
Packit Service a04d08
            #cloud-config
Packit Service a04d08
            # comment
Packit Service a04d08
            ntp:
Packit Service a04d08
              pools: [-99, 75]
Packit Service a04d08
            """).encode()
Packit Service a04d08
        expected = dedent("""\
Packit Service a04d08
            #cloud-config
Packit Service a04d08
            # comment
Packit Service a04d08
            ntp:		# E1
Packit Service a04d08
              pools: [-99, 75]		# E2,E3
Packit Service a04d08
Packit Service a04d08
            # Errors: -------------
Packit Service a04d08
            # E1: Some type error
Packit Service a04d08
            # E2: -99 is not a string
Packit Service a04d08
            # E3: 75 is not a string
Packit Service a04d08
Packit Service a04d08
            """)
Packit Service a04d08
        parsed_config = safe_load(content[13:])
Packit Service a04d08
        schema_errors = [
Packit Service a04d08
            ('ntp', 'Some type error'), ('ntp.pools.0', '-99 is not a string'),
Packit Service a04d08
            ('ntp.pools.1', '75 is not a string')]
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            expected,
Packit Service a04d08
            annotated_cloudconfig_file(parsed_config, content, schema_errors))
Packit Service a04d08
Packit Service a04d08
    def test_annotated_cloudconfig_file_annotates_separate_line_items(self):
Packit Service a04d08
        """Errors are annotated for lists with items on separate lines."""
Packit Service a04d08
        content = dedent("""\
Packit Service a04d08
            #cloud-config
Packit Service a04d08
            # comment
Packit Service a04d08
            ntp:
Packit Service a04d08
              pools:
Packit Service a04d08
                - -99
Packit Service a04d08
                - 75
Packit Service a04d08
            """).encode()
Packit Service a04d08
        expected = dedent("""\
Packit Service a04d08
            ntp:
Packit Service a04d08
              pools:
Packit Service a04d08
                - -99		# E1
Packit Service a04d08
                - 75		# E2
Packit Service a04d08
            """)
Packit Service a04d08
        parsed_config = safe_load(content[13:])
Packit Service a04d08
        schema_errors = [
Packit Service a04d08
            ('ntp.pools.0', '-99 is not a string'),
Packit Service a04d08
            ('ntp.pools.1', '75 is not a string')]
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            expected,
Packit Service a04d08
            annotated_cloudconfig_file(parsed_config, content, schema_errors))
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class MainTest(CiTestCase):
Packit Service a04d08
Packit Service a04d08
    def test_main_missing_args(self):
Packit Service a04d08
        """Main exits non-zero and reports an error on missing parameters."""
Packit Service 11b429
        with mock.patch('sys.exit', side_effect=self.sys_exit):
Packit Service 11b429
            with mock.patch('sys.argv', ['mycmd']):
Packit Service 11b429
                with mock.patch('sys.stderr', new_callable=StringIO) as \
Packit Service 11b429
                        m_stderr:
Packit Service 11b429
                    with self.assertRaises(SystemExit) as context_manager:
Packit Service 11b429
                        main()
Packit Service a04d08
        self.assertEqual(1, context_manager.exception.code)
Packit Service a04d08
        self.assertEqual(
Packit Service 11b429
            'Expected either --config-file argument or --doc\n',
Packit Service a04d08
            m_stderr.getvalue())
Packit Service a04d08
Packit Service a04d08
    def test_main_absent_config_file(self):
Packit Service a04d08
        """Main exits non-zero when config file is absent."""
Packit Service a04d08
        myargs = ['mycmd', '--annotate', '--config-file', 'NOT_A_FILE']
Packit Service 11b429
        with mock.patch('sys.exit', side_effect=self.sys_exit):
Packit Service 11b429
            with mock.patch('sys.argv', myargs):
Packit Service 11b429
                with mock.patch('sys.stderr', new_callable=StringIO) as \
Packit Service 11b429
                        m_stderr:
Packit Service 11b429
                    with self.assertRaises(SystemExit) as context_manager:
Packit Service 11b429
                        main()
Packit Service a04d08
        self.assertEqual(1, context_manager.exception.code)
Packit Service a04d08
        self.assertEqual(
Packit Service a04d08
            'Configfile NOT_A_FILE does not exist\n',
Packit Service a04d08
            m_stderr.getvalue())
Packit Service a04d08
Packit Service a04d08
    def test_main_prints_docs(self):
Packit Service 11b429
        """When --doc parameter is provided, main generates documentation."""
Packit Service 11b429
        myargs = ['mycmd', '--doc']
Packit Service a04d08
        with mock.patch('sys.argv', myargs):
Packit Service a04d08
            with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit Service a04d08
                self.assertEqual(0, main(), 'Expected 0 exit code')
Packit Service a04d08
        self.assertIn('\nNTP\n---\n', m_stdout.getvalue())
Packit Service a04d08
        self.assertIn('\nRuncmd\n------\n', m_stdout.getvalue())
Packit Service a04d08
Packit Service a04d08
    def test_main_validates_config_file(self):
Packit Service a04d08
        """When --config-file parameter is provided, main validates schema."""
Packit Service a04d08
        myyaml = self.tmp_path('my.yaml')
Packit Service a04d08
        myargs = ['mycmd', '--config-file', myyaml]
Packit Service a04d08
        write_file(myyaml, b'#cloud-config\nntp:')  # shortest ntp schema
Packit Service a04d08
        with mock.patch('sys.argv', myargs):
Packit Service a04d08
            with mock.patch('sys.stdout', new_callable=StringIO) as m_stdout:
Packit Service a04d08
                self.assertEqual(0, main(), 'Expected 0 exit code')
Packit Service a04d08
        self.assertIn(
Packit Service a04d08
            'Valid cloud-config file {0}'.format(myyaml), m_stdout.getvalue())
Packit Service a04d08
Packit Service a04d08
Packit Service a04d08
class CloudTestsIntegrationTest(CiTestCase):
Packit Service a04d08
    """Validate all cloud-config yaml schema provided in integration tests.
Packit Service a04d08
Packit Service a04d08
    It is less expensive to have unittests validate schema of all cloud-config
Packit Service a04d08
    yaml provided to integration tests, than to run an integration test which
Packit Service a04d08
    raises Warnings or errors on invalid cloud-config schema.
Packit Service a04d08
    """
Packit Service a04d08
Packit Service a04d08
    @skipUnlessJsonSchema()
Packit Service a04d08
    def test_all_integration_test_cloud_config_schema(self):
Packit Service a04d08
        """Validate schema of cloud_tests yaml files looking for warnings."""
Packit Service a04d08
        schema = get_schema()
Packit Service a04d08
        testsdir = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
Packit Service a04d08
        integration_testdir = os.path.sep.join(
Packit Service a04d08
            [testsdir, 'cloud_tests', 'testcases'])
Packit Service a04d08
        errors = []
Packit Service a04d08
Packit Service a04d08
        yaml_files = []
Packit Service a04d08
        for root, _dirnames, filenames in os.walk(integration_testdir):
Packit Service a04d08
            yaml_files.extend([os.path.join(root, f)
Packit Service a04d08
                               for f in filenames if f.endswith(".yaml")])
Packit Service a04d08
        self.assertTrue(len(yaml_files) > 0)
Packit Service a04d08
Packit Service a04d08
        for filename in yaml_files:
Packit Service a04d08
            test_cfg = safe_load(open(filename))
Packit Service a04d08
            cloud_config = test_cfg.get('cloud_config')
Packit Service a04d08
            if cloud_config:
Packit Service a04d08
                cloud_config = safe_load(
Packit Service a04d08
                    cloud_config.replace("#cloud-config\n", ""))
Packit Service a04d08
                try:
Packit Service a04d08
                    validate_cloudconfig_schema(
Packit Service a04d08
                        cloud_config, schema, strict=True)
Packit Service a04d08
                except SchemaValidationError as e:
Packit Service a04d08
                    errors.append(
Packit Service a04d08
                        '{0}: {1}'.format(
Packit Service a04d08
                            filename, e))
Packit Service a04d08
        if errors:
Packit Service a04d08
            raise AssertionError(', '.join(errors))
Packit Service a04d08
Packit Service a04d08
# vi: ts=4 expandtab syntax=python