Exemple #1
0
def test_config_strict_mode_errors():
    config.register(Item, strict_mode=True)

    test_config_path = testing.relative_module_path(__file__,
                                                    'test_config.yaml')

    with pytest.raises(ConfigLoadError, match='missing type declaration'):
        config.load_config(test_config_path)
Exemple #2
0
def test_config_with_simple_classes():

    # Another method for registering items (other than using decorator).
    config.register(Item)

    test_config_path = testing.relative_module_path(__file__,
                                                    'test_config.yaml')

    data = config.load_config(test_config_path)

    foo_with_defaults = data['foo_with_defaults']
    assert foo_with_defaults.f == 1

    empty_boo = data['empty_boo']
    assert empty_boo.foo is None

    foo = data['foo']
    boo = data['boo']

    assert foo.s == 'some_string'
    assert foo.f == 2.5

    assert boo.foo is foo
    assert len(boo.items) == 2
    assert isinstance(boo.items[0], Item)
Exemple #3
0
def test_config_unsafe_object_creation():
    from ruamel import yaml
    import calendar

    test_config_path = testing.relative_module_path(__file__,
                                                    'test_config_unsafe.yaml')

    # Unsafe default loader allows any python object initialization
    data = yaml.load(open(test_config_path), Loader=yaml.Loader)
    assert 'time' in data
    assert isinstance(data['time'], calendar.Calendar)

    # With use safe version only to allow construct previously registered objects
    with pytest.raises(config.ConfigLoadError,
                       match='could not determine a constructor'):
        config.load_config(test_config_path)
Exemple #4
0
def test_dataclass():
    test_config_path = testing.relative_module_path(__file__,
                                                    'test_dataclasses.yaml')
    data = config.load_config(test_config_path)

    dc1 = data['dc1']
    assert dc1.x == 5
    assert dc1.y == 'bleblo'
    assert dc1.z == [1, 2, 3]
    assert dc1.d == 'asd'

    dc2 = data['dc2']
    assert dc2.x == 1
    assert dc2.y == 'newble'
    assert dc2.z == [3, 4, 5]
    assert dc2.d == 4
def test_dataclass():
    test_config_path = testing.relative_module_path(__file__,
                                                    'test_dataclasses.yaml')
    data = config.load_config(test_config_path)

    dc1 = data['dc1']
    assert dc1.x == 5
    assert dc1.y is None
    assert dc1.z == [1, 2, 3]
    assert dc1.d == 'asd'
    assert dc1.foo == 'foobaz'

    dc2 = data['dc2']
    assert dc2.x == 1
    assert dc2.y == 'newble'
    assert dc2.z == [3, 4, 5]
    assert dc2.d == 4
    assert dc2.foo == FooEnum.BAR
Exemple #6
0
def test_dataclass_validation_invalid_dict():
    test_config_path = testing.relative_module_path(__file__,
                                                    'test_dataclasses_validation_invalid_dict.yaml')
    with pytest.raises(ConfigLoadError, match='wrong_value'):
        config.load_config(test_config_path)
Exemple #7
0
def test_dataclass_validation():
    test_config_path = testing.relative_module_path(__file__, 'test_dataclasses_validation.yaml')
    data = config.load_config(test_config_path)
    assert data['dc1'].rr == [[2, 3], []]
def test_dataclass_invalid_field():
    test_config_path = testing.relative_module_path(
        __file__, 'test_dataclasses_invalid_field.yaml')
    with pytest.raises(config.ConfigLoadError, match="constructor signature"):
        config.load_config(test_config_path)
def test_invalid_dataclass_union():
    test_config_path = testing.relative_module_path(
        __file__, 'test_dataclasses_invalid_union.yaml')
    with pytest.raises(config.ConfigLoadError,
                       match="field 'd'.*improper type from union"):
        config.load_config(test_config_path)
Exemple #10
0
def test_invalid_dataclass():
    test_config_path = testing.relative_module_path(
        __file__, 'test_dataclasses_invalid.yaml')
    with pytest.raises(config.ConfigLoadError, match="has improper type"):
        config.load_config(test_config_path)
Exemple #11
0
def main():

    parser = argparse.ArgumentParser()
    parser.add_argument(
        '-c', '--config',
        help="Configuration", default=None, required=True)
    parser.add_argument(
        '-l',
        '--log-level',
        help='Log level for modules (by default for owca) in [module:]level form,'
             'where level can be one of: CRITICAL,ERROR,WARNING,INFO,DEBUG,TRACE'
             'Example -l debug -l example:debug. Defaults to owca:INFO.'
             'Can be overridden at runtime with config.yaml "loggers" section.',
        default=[],
        action='append',
        dest='levels',
    )
    parser.add_argument(
        '-r', '--register', action='append', dest='components',
        help="Register additional components in config", default=[])
    parser.add_argument(
        '-v', '--version', action='version', version=platforms.get_owca_version(),
        help="Show version")
    parser.add_argument(
        '-0', '--root', help="Allow OWCA process to be run using root account",
        dest='is_root_allowed', action='store_true')

    args = parser.parse_args()

    # Do not allow to run OWCA with root privileges unless user indicates that it is intended.
    uid = os.geteuid()
    if uid == 0 and not args.is_root_allowed:
        log.fatal("Do not run OWCA with root privileges. Consult documentation "
                  "to understand what capabilities are required. If root account "
                  "has to be used then set --root/-0 argument to override.")
        exit(2)

    # Initialize logging subsystem from command line options.
    log_levels = logger.parse_loggers_from_list(args.levels)
    log_levels.setdefault(logger.DEFAULT_MODULE, 'info')
    logger.configure_loggers_from_dict(log_levels)

    log.warn('This software is pre-production and should not be deployed to production servers.')
    log.debug('started PID=%r', os.getpid())
    log.info('Version owca: %s', platforms.get_owca_version())

    # Register internal & external components.
    components.register_components(extra_components=args.components)

    # Initialize all necessary objects.
    try:
        configuration = config.load_config(args.config)
    except config.ConfigLoadError as e:
        log.error('Error: Cannot load config file %r: %s', args.config, e)
        if log.getEffectiveLevel() <= logging.DEBUG:
            log.exception('Detailed exception:')
        exit(1)

    # Configure loggers using configuration file.
    if 'loggers' in configuration:
        log_levels_config = configuration['loggers']
        if not isinstance(log_levels, dict):
            log.error('Loggers configuration error: log levels are mapping from logger name to'
                      'log level got "%r" instead!' % log_levels_config)
            exit(1)
        # Merge config from cmd line and config file.
        # Overide config file values with values provided from command line.
        log_levels = dict(log_levels, **log_levels_config)
        logger.configure_loggers_from_dict(log_levels)

    # Dump loggers configurations  to debug issues with loggers.
    if os.environ.get('OWCA_DUMP_LOGGERS') == 'True':
        print('------------------------------------ Logging tree ---------------------')
        import logging_tree
        logging_tree.printout()
        print('------------------------------------ Logging tree END------------------')

    # Extract main loop component.
    runner = configuration['runner']

    # Prepare and run the "main loop".
    runner.run()