Ejemplo n.º 1
0
    class Meta:

        name = N_('file')

        validator_cls = FileUnitValidator

        class fields(SymbolDef):
            """
            Symbols for each field that a FileUnit can have
            """
            path = 'path'
            role = 'role'
            base = 'base'

        field_validators = {
            fields.path: [
                CorrectFieldValueValidator(
                    lambda value: os.path.splitext(value)[1] == '.pxu',
                    Problem.deprecated,
                    Severity.advice,
                    onlyif=lambda unit: unit.role == FileRole.unit_source,
                    message=_(
                        "please use .pxu as an extension for all"
                        " files with plainbox units, see: {}").format(
                            'http://plainbox.readthedocs.org/en/latest/author/'
                            'faq.html#faq-1')),
            ],
            fields.role: [
                CorrectFieldValueValidator(
                    lambda value: value in FileRole.get_all_symbols(),
                    message=_('valid values are: {}').format(', '.join(
                        str(sym)
                        for sym in sorted(FileRole.get_all_symbols())))),
            ]
        }
Ejemplo n.º 2
0
    class Meta:

        name = N_('category')

        class fields(SymbolDef):
            """
            Symbols for each field that a JobDefinition can have
            """
            name = 'name'

        field_validators = {
            fields.name: [
                TranslatableFieldValidator,
                TemplateVariantFieldValidator,
                PresentFieldValidator,
                # We want the name to be a single line
                CorrectFieldValueValidator(
                    lambda name: name.count("\n") == 0,
                    Problem.wrong, Severity.warning,
                    message=_("please use only one line"),
                    onlyif=lambda unit: unit.name is not None),
                # We want the name to be relatively short
                CorrectFieldValueValidator(
                    lambda name: len(name) <= 80,
                    Problem.wrong, Severity.warning,
                    message=_("please stay under 80 characters"),
                    onlyif=lambda unit: unit.name is not None),
            ]
        }
Ejemplo n.º 3
0
    class Meta:

        name = 'exporter'

        class fields(SymbolDef):

            """Symbols for each field that an Exporter can have."""

            summary = 'summary'
            entry_point = 'entry_point'
            file_extension = 'file_extension'
            options = 'options'
            data = 'data'

        field_validators = {
            fields.summary: [
                PresentFieldValidator(severity=Severity.advice),
                concrete_validators.translatable,
                concrete_validators.oneLine,
                concrete_validators.shortValue,
            ],
            fields.entry_point: [
                concrete_validators.present,
                concrete_validators.untranslatable,
                CorrectFieldValueValidator(
                    lambda entry_point: pkg_resources.load_entry_point(
                        'checkbox-ng', 'plainbox.exporter', entry_point),
                    Problem.wrong, Severity.error),
            ],
            fields.file_extension: [
                concrete_validators.present,
                concrete_validators.untranslatable,
                CorrectFieldValueValidator(
                    lambda extension: re.search("^[\w\.\-]+$", extension),
                    Problem.syntax_error, Severity.error),
            ],
            fields.options: [
                concrete_validators.untranslatable,
            ],
            fields.data: [
                concrete_validators.untranslatable,
                CorrectFieldValueValidator(
                    lambda value, unit: json.loads(value),
                    Problem.syntax_error, Severity.error,
                    onlyif=lambda unit: unit.data),
                CorrectFieldValueValidator(
                    lambda value, unit: os.path.isfile(os.path.join(
                        unit.provider.data_dir,
                        json.loads(value)['template'])),
                    Problem.wrong, Severity.error,
                    message=_("Jinja2 template not found"),
                    onlyif=lambda unit: unit.entry_point == 'jinja2'),
            ],
        }
Ejemplo n.º 4
0
    class Meta:

        name = N_('unit-with-id')

        class fields(SymbolDef):
            id = 'id'

        validator_cls = UnitWithIdValidator

        field_validators = {
            fields.id: [
                # We don't want anyone marking id up for translation
                UntranslatableFieldValidator,
                # We want this field to be present at all times
                PresentFieldValidator,
                # We want each instance to have a different identifier
                TemplateVariantFieldValidator,
                # When checking in a globally, all units need an unique value
                UniqueValueValidator,
                # We want to have bare, namespace-less identifiers
                CorrectFieldValueValidator(
                    lambda value, unit: (
                        "::" not in unit.get_record_value('id')),
                    message=_("identifier cannot define a custom namespace"),
                    onlyif=lambda unit: unit.get_record_value('id')),
            ]
        }
Ejemplo n.º 5
0
    class Meta:

        name = 'manifest entry'

        class fields(SymbolDef):

            """ Symbols for each field that a TestPlan can have. """

            name = 'name'
            value_type = 'value-type'
            value_unit = 'value-unit'
            resource_key = 'resource-key'

        field_validators = {
            fields.name: [
                TranslatableFieldValidator,
                TemplateVariantFieldValidator,
                PresentFieldValidator,
            ],
            fields.value_type: [
                UntranslatableFieldValidator,
                PresentFieldValidator(),
                CorrectFieldValueValidator(
                    lambda value_type: value_type in ('bool', 'natural')),
            ],
            fields.value_unit: [
                # OPTIONAL
            ],
            fields.resource_key: [
                UntranslatableFieldValidator,
            ]
        }
Ejemplo n.º 6
0
    class Meta:

        name = N_('unit-with-id')

        class fields(SymbolDef):
            id = 'id'

        validator_cls = UnitWithIdValidator

        field_validators = {
            fields.id: [
                concrete_validators.untranslatable,
                concrete_validators.present,
                concrete_validators.templateVariant,
                UniqueValueValidator(),
                # We want to have bare, namespace-less identifiers
                CorrectFieldValueValidator(
                    lambda value, unit:
                    ("::" not in unit.get_record_value('id')),
                    message=_("identifier cannot define a custom namespace"),
                    onlyif=lambda unit: unit.get_record_value('id')),
            ]
        }
Ejemplo n.º 7
0
    class Meta:

        name = N_('job')

        class fields(SymbolDef):
            """
            Symbols for each field that a JobDefinition can have
            """
            name = 'name'
            summary = 'summary'
            plugin = 'plugin'
            command = 'command'
            description = 'description'
            user = '******'
            environ = 'environ'
            estimated_duration = 'estimated_duration'
            depends = 'depends'
            after = 'after'
            requires = 'requires'
            shell = 'shell'
            imports = 'imports'
            flags = 'flags'
            category_id = 'category_id'
            purpose = 'purpose'
            steps = 'steps'
            verification = 'verification'
            qml_file = 'qml_file'
            certification_status = 'certification_status'

        field_validators = {
            fields.name: [
                UntranslatableFieldValidator,
                TemplateVariantFieldValidator,
                DeprecatedFieldValidator(
                    _("use 'id' and 'summary' instead of 'name'")),
            ],
            # NOTE: 'id' validators are "inherited" so we don't have it here
            fields.summary: [
                TranslatableFieldValidator,
                TemplateVariantFieldValidator,
                PresentFieldValidator(severity=Severity.advice),
                # We want the summary to be a single line
                CorrectFieldValueValidator(
                    lambda summary: summary.count("\n") == 0,
                    Problem.wrong, Severity.warning,
                    message=_("please use only one line"),
                    onlyif=lambda unit: unit.summary is not None),
                # We want the summary to be relatively short
                CorrectFieldValueValidator(
                    lambda summary: len(summary) <= 80,
                    Problem.wrong, Severity.warning,
                    message=_("please stay under 80 characters"),
                    onlyif=lambda unit: unit.summary is not None),
            ],
            fields.plugin: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                PresentFieldValidator,
                CorrectFieldValueValidator(
                    lambda plugin: (
                        plugin in JobDefinition.plugin.get_all_symbols()),
                    message=_('valid values are: {}').format(
                        ', '.join(str(sym) for sym in sorted(
                            _PluginValues.get_all_symbols())))),
                CorrectFieldValueValidator(
                    lambda plugin: plugin != 'local',
                    Problem.deprecated, Severity.advice,
                    message=_("please migrate to job templates, "
                              "see plainbox-template-unit(7) for details")),
                CorrectFieldValueValidator(
                    lambda plugin: plugin != 'user-verify',
                    Problem.deprecated, Severity.advice,
                    message=_("please migrate to user-interact-verify")),
            ],
            fields.command: [
                UntranslatableFieldValidator,
                # All jobs except for manual must have a command
                PresentFieldValidator(
                    message=_("command is mandatory for non-manual jobs"),
                    onlyif=lambda unit: unit.plugin not in ('manual', 'qml')),
                # Manual jobs cannot have a command
                UselessFieldValidator(
                    message=_("command on a manual or qml job makes no sense"),
                    onlyif=lambda unit: unit.plugin in ('manual', 'qml')),
                # We don't want to refer to CHECKBOX_SHARE anymore
                CorrectFieldValueValidator(
                    lambda command: "CHECKBOX_SHARE" not in command,
                    Problem.deprecated, Severity.advice,
                    message=_("please use PLAINBOX_PROVIDER_DATA"
                              " instead of CHECKBOX_SHARE"),
                    onlyif=lambda unit: unit.command is not None),
                # We don't want to refer to CHECKBOX_DATA anymore
                CorrectFieldValueValidator(
                    lambda command: "CHECKBOX_DATA" not in command,
                    Problem.deprecated, Severity.advice,
                    message=_("please use PLAINBOX_SESSION_SHARE"
                              " instead of CHECKBOX_DATA"),
                    onlyif=lambda unit: unit.command is not None),
                # We want to catch silly mistakes that shlex can detect
                ShellProgramValidator,
            ],
            fields.description: [
                TranslatableFieldValidator,
                TemplateVariantFieldValidator,
                # Description is mandatory for manual jobs
                PresentFieldValidator(
                    message=_("manual jobs must have a description field, or a"
                              " set of purpose, steps, and verification "
                              "fields"),
                    onlyif=lambda unit: unit.plugin == 'manual' and
                    unit.purpose is None and unit.steps is None and
                    unit.verification is None
                    ),
                # Description or a set of purpose, steps and verification
                # fields is recommended for all other jobs
                PresentFieldValidator(
                    severity=Severity.advice,
                    message=_("all jobs should have a description field, or a "
                              "set of purpose, steps and verification fields"),
                    onlyif=lambda unit: (
                        'simple' not in unit.get_flag_set() and
                        unit.plugin != 'manual' and (
                            unit.purpose is None and
                            unit.steps is None and
                            unit.verification is None))),
            ],
            fields.purpose: [
                TranslatableFieldValidator,
                PresentFieldValidator(
                    severity=Severity.advice,
                    message=("please use purpose, steps, and verification"
                             " fields. See http://plainbox.readthedocs.org"
                             "/en/latest/author/faq.html#faq-2"),
                    onlyif=lambda unit:
                    unit.startup_user_interaction_required and
                    unit.get_record_value('summary') is None),
            ],
            fields.steps: [
                TranslatableFieldValidator,
                PresentFieldValidator(
                    severity=Severity.advice,
                    message=("please use purpose, steps, and verification"
                             " fields. See http://plainbox.readthedocs.org"
                             "/en/latest/author/faq.html#faq-2"),
                    onlyif=lambda unit:
                    unit.startup_user_interaction_required),
            ],
            fields.verification: [
                TranslatableFieldValidator,
                PresentFieldValidator(
                    severity=Severity.advice,
                    message=("please use purpose, steps, and verification"
                             " fields. See http://plainbox.readthedocs.org"
                             "/en/latest/author/faq.html#faq-2"),
                    onlyif=lambda unit: unit.plugin in (
                        'manual', 'user-verify', 'user-interact-verify')),
            ],
            fields.user: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                # User should be either None or 'root'
                CorrectFieldValueValidator(
                    message=_("user can only be 'root'"),
                    correct_fn=lambda user: user in (None, 'root')),
                # User is useless without a command to run
                UselessFieldValidator(
                    message=_("user without a command makes no sense"),
                    onlyif=lambda unit: unit.command is None)
            ],
            fields.environ: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                # Environ is useless without a command to run
                UselessFieldValidator(
                    message=_("environ without a command makes no sense"),
                    onlyif=lambda unit: unit.command is None),
            ],
            fields.estimated_duration: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                PresentFieldValidator(
                    severity=Severity.advice,
                    onlyif=lambda unit: 'simple' not in unit.get_flag_set()
                ),
                CorrectFieldValueValidator(
                    lambda duration: float(duration) > 0,
                    message="value must be a positive number",
                    onlyif=lambda unit: (
                        unit.get_record_value('estimated_duration'))),
            ],
            fields.depends: [
                UntranslatableFieldValidator,
                CorrectFieldValueValidator(
                    lambda value, unit: (
                        unit.get_direct_dependencies() is not None)),
                UnitReferenceValidator(
                    lambda unit: unit.get_direct_dependencies(),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job"))])
                # TODO: should not refer to deprecated jobs,
                #       onlyif job itself is not deprecated
            ],
            fields.after: [
                UntranslatableFieldValidator,
                CorrectFieldValueValidator(
                    lambda value, unit: (
                        unit.get_after_dependencies() is not None)),
                UnitReferenceValidator(
                    lambda unit: unit.get_after_dependencies(),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job"))])
            ],
            fields.requires: [
                UntranslatableFieldValidator,
                CorrectFieldValueValidator(
                    lambda value, unit: unit.get_resource_program(),
                    onlyif=lambda unit: unit.requires is not None),
                UnitReferenceValidator(
                    lambda unit: unit.get_resource_dependencies(),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job")),
                        ReferenceConstraint(
                            lambda referrer, referee: (
                                referee.plugin == 'resource'),
                            onlyif=lambda referrer, referee: (
                                referee.unit == 'job'),
                            message=_(
                                "the referenced job is not a resource job")),
                    ]),
                # TODO: should not refer to deprecated jobs,
                #       onlyif job itself is not deprecated
            ],
            fields.shell: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                # Shell should be only '/bin/sh', or None (which gives bash)
                CorrectFieldValueValidator(
                    lambda shell: shell in ('/bin/sh', '/bin/bash', 'bash'),
                    message=_("only /bin/sh and /bin/bash are allowed")),
            ],
            fields.imports: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                CorrectFieldValueValidator(
                    lambda value, unit: (
                        list(unit.get_imported_jobs()) is not None)),
                UnitReferenceValidator(
                    lambda unit: [
                        job_id
                        for job_id, identifier in unit.get_imported_jobs()],
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job"))]),
                # TODO: should not refer to deprecated jobs,
                #       onlyif job itself is not deprecated
            ],
            fields.category_id: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                UnitReferenceValidator(
                    lambda unit: (
                        [unit.get_category_id()] if unit.category_id else ()),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: (
                                referee.unit == 'category'),
                            message=_(
                                "the referenced unit is not a category"))]),
                # TODO: should not refer to deprecated categories,
                #       onlyif job itself is not deprecated
            ],
            fields.flags: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                CorrectFieldValueValidator(
                    lambda value, unit: (
                        'simple' in unit.get_flag_set() or
                        'preserve-locale' in unit.get_flag_set()),
                    Problem.expected_i18n, Severity.advice,
                    message=_(
                        'please ensure that the command supports'
                        ' non-C locale then set the preserve-locale flag'
                    ),
                    onlyif=lambda unit: unit.command),
                CorrectFieldValueValidator(
                    lambda value, unit: (
                        not ('explicit-fail' in unit.get_flag_set() and
                             unit.plugin in {
                                 'shell', 'user-interact', 'attachment',
                                 'local', 'resource'})),
                    Problem.useless, Severity.advice,
                    message=_('explicit-fail makes no sense for job which '
                              'outcome is automatically determined.')
                ),
                # The has-leftovers flag is useless without a command
                CorrectFieldValueValidator(
                    lambda value, unit: (
                        'has-leftovers' not in unit.get_flag_set()),
                    Problem.useless, Severity.advice,
                    message=_(
                        'has-leftovers makes no sense without a command'
                    ),
                    onlyif=lambda unit: unit.command is None),
            ],
            fields.qml_file: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                PresentFieldValidator(
                    onlyif=lambda unit: unit.plugin == 'qml'),
                CorrectFieldValueValidator(
                    lambda value: value.endswith('.qml'),
                    Problem.wrong, Severity.advice,
                    message=_('use the .qml extension for all QML files'),
                    onlyif=lambda unit: (unit.plugin == 'qml' and
                                         unit.qml_file)),
                CorrectFieldValueValidator(
                    lambda value, unit: os.path.isfile(unit.qml_file),
                    message=_('please point to an existing QML file'),
                    onlyif=lambda unit: (unit.plugin == 'qml' and
                                         unit.qml_file)),
            ],
            fields.certification_status: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                CorrectFieldValueValidator(
                    lambda certification_status: (
                        certification_status in
                        _CertificationStatusValues.get_all_symbols()),
                    message=_('valid values are: {}').format(
                        ', '.join(str(sym) for sym in sorted(
                            _CertificationStatusValues.get_all_symbols())))),
            ],
        }
Ejemplo n.º 8
0
from plainbox.impl.unit.validators import PresentFieldValidator
from plainbox.impl.unit.validators import TemplateInvariantFieldValidator
from plainbox.impl.unit.validators import TemplateVariantFieldValidator
from plainbox.impl.unit.validators import TranslatableFieldValidator
from plainbox.impl.unit.validators import UntranslatableFieldValidator

translatable = TranslatableFieldValidator()
templateVariant = TemplateVariantFieldValidator()
templateInvariant = TemplateInvariantFieldValidator()
untranslatable = UntranslatableFieldValidator()
present = PresentFieldValidator()

localDeprecated = CorrectFieldValueValidator(
    lambda plugin: plugin != 'local',
    Problem.deprecated,
    Severity.advice,
    message=_("please migrate to job templates, see plainbox-template-unit(7)"
              " for details"))

oneLine = CorrectFieldValueValidator(
    lambda field: field is not None and field.count("\n") == 0,
    Problem.wrong,
    Severity.warning,
    message=_("please use only one line"))

shortValue = CorrectFieldValueValidator(
    lambda field: field is not None and len(field) <= 80,
    Problem.wrong,
    Severity.warning,
    message=_("please stay under 80 characters"))
Ejemplo n.º 9
0
    class Meta:

        name = N_('template')

        class fields(SymbolDef):
            """Symbols for each field that a TemplateUnit can have."""

            template_unit = 'template-unit'
            template_resource = 'template-resource'
            template_filter = 'template-filter'
            template_imports = 'template-imports'

        validator_cls = TemplateUnitValidator

        field_validators = {
            fields.template_unit: [
                concrete_validators.untranslatable,
                CorrectFieldValueValidator(
                    lambda value, unit:
                    (unit.get_record_value('template-unit') is not None),
                    Problem.missing,
                    Severity.advice,
                    message=_("template should explicitly define instantiated"
                              " unit type")),
            ],
            fields.template_resource: [
                concrete_validators.untranslatable,
                concrete_validators.present,
                UnitReferenceValidator(
                    lambda unit: ([unit.resource_id]
                                  if unit.resource_id else []),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job")),
                        ReferenceConstraint(
                            lambda referrer, referee:
                            (referee.plugin == 'resource'),
                            onlyif=lambda referrer, referee:
                            (referee.unit == 'job'),
                            message=_(
                                "the referenced job is not a resource job")),
                    ]),
                # TODO: should not refer to deprecated job,
                #       onlyif job itself is not deprecated
            ],
            fields.template_filter: [
                concrete_validators.untranslatable,
                # All templates need a valid (or empty) template filter
                CorrectFieldValueValidator(
                    lambda value, unit: unit.get_filter_program(),
                    onlyif=lambda unit: unit.template_filter is not None),
                # TODO: must refer to the same job as template-resource
            ],
            fields.template_imports: [
                concrete_validators.untranslatable,
                CorrectFieldValueValidator(lambda value, unit: (list(
                    unit.get_imported_jobs()) is not None)),
                CorrectFieldValueValidator(
                    lambda value, unit: (len(list(unit.get_imported_jobs())) in
                                         (0, 1)),
                    message=_("at most one import statement is allowed")),
                # TODO: must refer to known or possibly-known job
                # TODO: should not refer to deprecated jobs,
                #       onlyif job itself is not deprecated
            ],
        }
Ejemplo n.º 10
0
    class Meta:

        name = 'test plan'

        class fields(SymbolDef):
            """
            Symbols for each field that a TestPlan can have
            """
            name = 'name'
            description = 'description'
            include = 'include'
            mandatory_include = 'mandatory_include'
            bootstrap_include = 'bootstrap_include'
            exclude = 'exclude'
            nested_part = 'nested_part'
            estimated_duration = 'estimated_duration'
            icon = 'icon'
            category_overrides = 'category-overrides'

        field_validators = {
            fields.name: [
                concrete_validators.translatable,
                concrete_validators.templateVariant,
                concrete_validators.present,
                concrete_validators.oneLine,
                concrete_validators.shortValue,
            ],
            fields.description: [
                concrete_validators.translatable,
                concrete_validators.templateVariant,
                PresentFieldValidator(
                    severity=Severity.advice,
                    onlyif=lambda unit: unit.virtual is False),
            ],
            fields.include: [
                NonEmptyPatternIntersectionValidator(),
                concrete_validators.present,
            ],
            fields.mandatory_include: [
                NonEmptyPatternIntersectionValidator(),
                NoBaseIncludeValidator(),
            ],
            fields.bootstrap_include: [
                concrete_validators.untranslatable,
                NoBaseIncludeValidator(),
                UnitReferenceValidator(
                    lambda unit: unit.get_bootstrap_job_ids(),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job")),
                        ReferenceConstraint(
                            lambda referrer, referee:
                            (referee.plugin in ['local', 'resource']),
                            message=_("only local and resource jobs are "
                                      "allowed in bootstrapping_include"))
                    ])
            ],
            fields.exclude: [
                NonEmptyPatternIntersectionValidator(),
            ],
            fields.nested_part: [
                NonEmptyPatternIntersectionValidator(),
            ],
            fields.estimated_duration: [
                concrete_validators.untranslatable,
                concrete_validators.templateInvariant,
                PresentFieldValidator(
                    severity=Severity.advice,
                    onlyif=lambda unit: unit.virtual is False),
                CorrectFieldValueValidator(
                    lambda duration, unit: unit.estimated_duration > 0,
                    message="value must be a positive number",
                    onlyif=lambda unit:
                    (unit.virtual is False and unit.get_record_value(
                        'estimated_duration'))),
            ],
            fields.icon: [
                concrete_validators.untranslatable,
            ],
            fields.category_overrides: [
                # optional
                # valid
                # referring to jobs correctly
                # referring to categories correctly
            ],
        }
"""

from plainbox.i18n import gettext as _
from plainbox.impl.unit.validators import CorrectFieldValueValidator
from plainbox.impl.validation import Problem
from plainbox.impl.validation import Severity

from plainbox.impl.unit.validators import PresentFieldValidator
from plainbox.impl.unit.validators import TemplateInvariantFieldValidator
from plainbox.impl.unit.validators import TemplateVariantFieldValidator
from plainbox.impl.unit.validators import TranslatableFieldValidator
from plainbox.impl.unit.validators import UntranslatableFieldValidator

translatable = TranslatableFieldValidator()
templateVariant = TemplateVariantFieldValidator()
templateInvariant = TemplateInvariantFieldValidator()
untranslatable = UntranslatableFieldValidator()
present = PresentFieldValidator()

oneLine = CorrectFieldValueValidator(
    lambda field: field is not None and field.count("\n") == 0,
    Problem.wrong,
    Severity.warning,
    message=_("please use only one line"))

shortValue = CorrectFieldValueValidator(
    lambda field: field is not None and len(field) <= 80,
    Problem.wrong,
    Severity.warning,
    message=_("please stay under 80 characters"))
Ejemplo n.º 12
0
    class Meta:

        name = N_('job')

        class fields(SymbolDef):
            """
            Symbols for each field that a JobDefinition can have
            """
            name = 'name'
            summary = 'summary'
            plugin = 'plugin'
            command = 'command'
            description = 'description'
            user = '******'
            environ = 'environ'
            estimated_duration = 'estimated_duration'
            depends = 'depends'
            after = 'after'
            salvages = 'salvages'
            requires = 'requires'
            shell = 'shell'
            imports = 'imports'
            flags = 'flags'
            category_id = 'category_id'
            purpose = 'purpose'
            steps = 'steps'
            verification = 'verification'
            certification_status = 'certification_status'
            siblings = 'siblings'
            auto_retry = 'auto_retry'

        field_validators = {
            fields.name: [
                concrete_validators.untranslatable,
                concrete_validators.templateVariant,
                DeprecatedFieldValidator(
                    _("use 'id' and 'summary' instead of 'name'")),
            ],
            # NOTE: 'id' validators are "inherited" so we don't have it here
            fields.summary: [
                concrete_validators.translatable,
                concrete_validators.templateVariant,
                PresentFieldValidator(severity=Severity.advice),
                concrete_validators.oneLine,
                concrete_validators.shortValue,
            ],
            fields.plugin: [
                concrete_validators.untranslatable,
                concrete_validators.templateInvariant,
                concrete_validators.present,
                MemberOfFieldValidator(_PluginValues.get_all_symbols()),
                CorrectFieldValueValidator(
                    lambda plugin: plugin != 'user-verify',
                    Problem.deprecated,
                    Severity.advice,
                    message=_("please migrate to user-interact-verify")),
            ],
            fields.command: [
                concrete_validators.untranslatable,
                # All jobs except for manual must have a command
                PresentFieldValidator(
                    message=_("command is mandatory for non-manual jobs"),
                    onlyif=lambda unit: unit.plugin != 'manual'),
                # Manual jobs cannot have a command
                UselessFieldValidator(
                    message=_("command on a manual job makes no sense"),
                    onlyif=lambda unit: unit.plugin == 'manual'),
                # We don't want to refer to CHECKBOX_SHARE anymore
                CorrectFieldValueValidator(
                    lambda command: "CHECKBOX_SHARE" not in command,
                    Problem.deprecated,
                    Severity.advice,
                    message=_("please use PLAINBOX_PROVIDER_DATA"
                              " instead of CHECKBOX_SHARE"),
                    onlyif=lambda unit: unit.command is not None),
                # We don't want to refer to CHECKBOX_DATA anymore
                CorrectFieldValueValidator(
                    lambda command: "CHECKBOX_DATA" not in command,
                    Problem.deprecated,
                    Severity.advice,
                    message=_("please use PLAINBOX_SESSION_SHARE"
                              " instead of CHECKBOX_DATA"),
                    onlyif=lambda unit: unit.command is not None),
                # We want to catch silly mistakes that shlex can detect
                ShellProgramValidator(),
            ],
            fields.description: [
                concrete_validators.translatable,
                concrete_validators.templateVariant,
                # Description is mandatory for manual jobs
                PresentFieldValidator(
                    message=_("manual jobs must have a description field, or a"
                              " set of purpose, steps, and verification "
                              "fields"),
                    onlyif=lambda unit: unit.plugin == 'manual' and unit.
                    purpose is None and unit.steps is None and unit.
                    verification is None),
                # Description or a set of purpose, steps and verification
                # fields is recommended for all other jobs
            ],
            fields.purpose: [
                concrete_validators.translatable,
            ],
            fields.steps: [
                concrete_validators.translatable,
            ],
            fields.verification: [
                concrete_validators.translatable,
            ],
            fields.user: [
                concrete_validators.untranslatable,
                concrete_validators.templateInvariant,
                # User should be either None or 'root'
                CorrectFieldValueValidator(
                    message=_("user can only be 'root'"),
                    correct_fn=lambda user: user in (None, 'root')),
                # User is useless without a command to run
                UselessFieldValidator(
                    message=_("user without a command makes no sense"),
                    onlyif=lambda unit: unit.command is None)
            ],
            fields.environ: [
                concrete_validators.untranslatable,
                # Environ is useless without a command to run
                UselessFieldValidator(
                    message=_("environ without a command makes no sense"),
                    onlyif=lambda unit: unit.command is None),
            ],
            fields.estimated_duration: [
                concrete_validators.untranslatable,
                concrete_validators.templateInvariant,
                CorrectFieldValueValidator(
                    lambda duration: float(duration) > 0,
                    message="value must be a positive number",
                    onlyif=lambda unit:
                    (unit.get_record_value('estimated_duration'))),
            ],
            fields.depends: [
                concrete_validators.untranslatable,
                CorrectFieldValueValidator(lambda value, unit: (
                    unit.get_direct_dependencies() is not None)),
                UnitReferenceValidator(
                    lambda unit: unit.get_direct_dependencies(),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job"))
                    ])
                # TODO: should not refer to deprecated jobs,
                #       onlyif job itself is not deprecated
            ],
            fields.after: [
                concrete_validators.untranslatable,
                CorrectFieldValueValidator(lambda value, unit: (
                    unit.get_after_dependencies() is not None)),
                UnitReferenceValidator(
                    lambda unit: unit.get_after_dependencies(),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job"))
                    ])
            ],
            fields.requires: [
                concrete_validators.untranslatable,
                CorrectFieldValueValidator(
                    lambda value, unit: unit.get_resource_program(),
                    onlyif=lambda unit: unit.requires is not None),
                UnitReferenceValidator(
                    lambda unit: unit.get_resource_dependencies(),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job")),
                        ReferenceConstraint(
                            lambda referrer, referee:
                            (referee.plugin == 'resource'),
                            onlyif=lambda referrer, referee:
                            (referee.unit == 'job'),
                            message=_(
                                "the referenced job is not a resource job")),
                    ]),
                # TODO: should not refer to deprecated jobs,
                #       onlyif job itself is not deprecated
            ],
            fields.shell: [
                concrete_validators.untranslatable,
                concrete_validators.templateInvariant,
                # Shell should be only '/bin/sh', or None (which gives bash)
                MemberOfFieldValidator(
                    ['/bin/sh', '/bin/bash', 'bash'],
                    message=_("only /bin/sh and /bin/bash are allowed")),
            ],
            fields.imports: [
                concrete_validators.untranslatable,
                concrete_validators.templateInvariant,
                CorrectFieldValueValidator(lambda value, unit: (list(
                    unit.get_imported_jobs()) is not None)),
                UnitReferenceValidator(
                    lambda unit: [
                        job_id
                        for job_id, identifier in unit.get_imported_jobs()
                    ],
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job"))
                    ]),
                # TODO: should not refer to deprecated jobs,
                #       onlyif job itself is not deprecated
            ],
            fields.category_id: [
                concrete_validators.untranslatable,
                concrete_validators.templateInvariant,
                UnitReferenceValidator(
                    lambda unit: ([unit.get_category_id()]
                                  if unit.category_id else ()),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee:
                            (referee.unit == 'category'),
                            message=_("the referenced unit is not a category"))
                    ]),
                # TODO: should not refer to deprecated categories,
                #       onlyif job itself is not deprecated
            ],
            fields.flags: [
                concrete_validators.untranslatable,
                concrete_validators.templateInvariant,
            ],
            fields.certification_status: [
                concrete_validators.untranslatable,
                concrete_validators.templateInvariant,
                MemberOfFieldValidator(
                    _CertificationStatusValues.get_all_symbols()),
            ],
            fields.siblings: [
                concrete_validators.translatable,
                CorrectFieldValueValidator(
                    lambda value, unit: json.loads(value),
                    Problem.syntax_error,
                    Severity.error,
                    onlyif=lambda unit: unit.siblings),
                CorrectFieldValueValidator(
                    lambda value, unit: type(json.loads(value)) is list,
                    Problem.syntax_error,
                    Severity.error,
                    onlyif=lambda unit: unit.siblings),
                CorrectFieldValueValidator(lambda value, unit: all(
                    [type(s) is dict for s in json.loads(value)]),
                                           Problem.syntax_error,
                                           Severity.error,
                                           onlyif=lambda unit: unit.siblings),
                CorrectFieldValueValidator(
                    lambda value, unit: all([
                        all([
                            hasattr(JobDefinition, k.lstrip('_'))
                            for k in s.keys()
                        ]) for s in json.loads(value)
                    ]),
                    Problem.bad_reference,
                    Severity.error,
                    message=_('unknown override job field'),
                    onlyif=lambda unit: unit.siblings),
            ],
            fields.auto_retry: [
                concrete_validators.untranslatable,
                concrete_validators.templateInvariant,
                MemberOfFieldValidator(_AutoRetryValues.get_all_symbols()),
            ],
        }
Ejemplo n.º 13
0
    class Meta:

        name = 'test plan'

        class fields(SymbolDef):
            """
            Symbols for each field that a TestPlan can have
            """
            name = 'name'
            description = 'description'
            include = 'include'
            mandatory_include = 'mandatory_include'
            bootstrap_include = 'bootstrap_include'
            exclude = 'exclude'
            estimated_duration = 'estimated_duration'
            icon = 'icon'
            category_overrides = 'category-overrides'

        field_validators = {
            fields.name: [
                TranslatableFieldValidator,
                TemplateVariantFieldValidator,
                PresentFieldValidator,
                # We want the summary to be a single line
                CorrectFieldValueValidator(
                    lambda name: name.count("\n") == 0,
                    Problem.wrong,
                    Severity.warning,
                    message=_("please use only one line"),
                    onlyif=lambda unit: unit.name is not None),
                # We want the summary to be relatively short
                CorrectFieldValueValidator(
                    lambda name: len(name) <= 80,
                    Problem.wrong,
                    Severity.warning,
                    message=_("please stay under 80 characters"),
                    onlyif=lambda unit: unit.name is not None),
            ],
            fields.description: [
                TranslatableFieldValidator,
                TemplateVariantFieldValidator,
                PresentFieldValidator(
                    severity=Severity.advice,
                    onlyif=lambda unit: unit.virtual is False),
            ],
            fields.include: [
                NonEmptyPatternIntersectionValidator,
                PresentFieldValidator(),
            ],
            fields.mandatory_include: [
                NonEmptyPatternIntersectionValidator,
                NoBaseIncludeValidator,
            ],
            fields.bootstrap_include: [
                UntranslatableFieldValidator, NoBaseIncludeValidator,
                UnitReferenceValidator(
                    lambda unit: unit.get_bootstrap_job_ids(),
                    constraints=[
                        ReferenceConstraint(
                            lambda referrer, referee: referee.unit == 'job',
                            message=_("the referenced unit is not a job")),
                        ReferenceConstraint(
                            lambda referrer, referee:
                            (referee.plugin in ['local', 'resource']),
                            message=_("only local and resource jobs are "
                                      "allowed in bootstrapping_include"))
                    ])
            ],
            fields.exclude: [
                NonEmptyPatternIntersectionValidator,
            ],
            fields.estimated_duration: [
                UntranslatableFieldValidator,
                TemplateInvariantFieldValidator,
                PresentFieldValidator(
                    severity=Severity.advice,
                    onlyif=lambda unit: unit.virtual is False),
                CorrectFieldValueValidator(
                    lambda duration, unit: unit.estimated_duration > 0,
                    message="value must be a positive number",
                    onlyif=lambda unit:
                    (unit.virtual is False and unit.get_record_value(
                        'estimated_duration'))),
            ],
            fields.icon: [
                UntranslatableFieldValidator,
            ],
            fields.category_overrides: [
                # optional
                # valid
                # referring to jobs correctly
                # referring to categories correctly
            ],
        }
Ejemplo n.º 14
0
    class Meta:

        name = 'exporter'

        class fields(SymbolDef):
            """Symbols for each field that an Exporter can have."""

            summary = 'summary'
            entry_point = 'entry_point'
            file_extension = 'file_extension'
            options = 'options'
            data = 'data'

        field_validators = {
            fields.summary: [
                PresentFieldValidator(severity=Severity.advice),
                TranslatableFieldValidator,
                # We want the summary to be a single line
                CorrectFieldValueValidator(
                    lambda summary: summary.count("\n") == 0,
                    Problem.wrong,
                    Severity.warning,
                    message=_("please use only one line"),
                    onlyif=lambda unit: unit.summary is not None),
                # We want the summary to be relatively short
                CorrectFieldValueValidator(
                    lambda summary: len(summary) <= 80,
                    Problem.wrong,
                    Severity.warning,
                    message=_("please stay under 80 characters"),
                    onlyif=lambda unit: unit.summary is not None),
            ],
            fields.entry_point: [
                PresentFieldValidator,
                UntranslatableFieldValidator,
                CorrectFieldValueValidator(
                    lambda entry_point: pkg_resources.load_entry_point(
                        'plainbox', 'plainbox.exporter', entry_point),
                    Problem.wrong, Severity.error),
            ],
            fields.file_extension: [
                PresentFieldValidator,
                UntranslatableFieldValidator,
                CorrectFieldValueValidator(
                    lambda extension: re.search("^[\w\.\-]+$", extension),
                    Problem.syntax_error, Severity.error),
            ],
            fields.options: [
                UntranslatableFieldValidator,
            ],
            fields.data: [
                UntranslatableFieldValidator,
                CorrectFieldValueValidator(
                    lambda value, unit: json.loads(value),
                    Problem.syntax_error,
                    Severity.error,
                    onlyif=lambda unit: unit.data),
                CorrectFieldValueValidator(
                    lambda value, unit: os.path.isfile(
                        os.path.join(unit.provider.data_dir,
                                     json.loads(value)['template'])),
                    Problem.wrong,
                    Severity.error,
                    message=_("Jinja2 template not found"),
                    onlyif=lambda unit: unit.entry_point == 'jinja2'),
            ],
        }