class Severity(SymbolDef, allow_outer={"N_"}):
    """
    Symbols for class:`Issue` severity
    """
    error = N_('error')
    warning = N_('warning')
    advice = N_('advice')
Ejemplo n.º 2
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.º 3
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: [MemberOfFieldValidator(FileRole.get_all_symbols())]
        }
Ejemplo n.º 4
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),
            ]
        }
def get_stubbox_def():
    """
    Get a Provider1Definition for stubbox
    """
    stubbox_def = Provider1Definition()
    stubbox_def.name = "com.canonical.plainbox:stubbox"
    stubbox_def.version = "1.0"
    stubbox_def.description = N_("StubBox (dummy data for development)")
    stubbox_def.secure = False
    stubbox_def.gettext_domain = "plainbox-provider-stubbox"
    stubbox_def.location = os.path.join(
        get_plainbox_dir(), "impl/providers/stubbox")
    return stubbox_def
def get_categories_def():
    """
    Get a Provider1Definition for the provider that knows all the categories
    """
    categories_def = Provider1Definition()
    categories_def.name = "com.canonical.plainbox:categories"
    categories_def.version = "1.0"
    categories_def.description = N_("Common test category definitions")
    categories_def.secure = False
    categories_def.gettext_domain = "plainbox-provider-categories"
    categories_def.location = os.path.join(
        get_plainbox_dir(), "impl/providers/categories")
    return categories_def
def get_manifest_def():
    """
    Get a Provider1Definition for the provider that handles the manifest
    machinery.
    """
    manifest_def = Provider1Definition()
    manifest_def.name = "com.canonical.plainbox:manifest"
    manifest_def.version = "1.0"
    manifest_def.description = N_("Hardware Manifest Provider")
    manifest_def.secure = False
    manifest_def.gettext_domain = "plainbox-provider-manifest"
    manifest_def.location = os.path.join(
        get_plainbox_dir(), "impl/providers/manifest")
    return manifest_def
def get_exporters_def():
    """
    Get a Provider1Definition for the provider that handles the exporters
    machinery.
    """
    exporters_def = Provider1Definition()
    exporters_def.name = "com.canonical.plainbox:exporters"
    exporters_def.version = "1.0"
    exporters_def.description = N_("Exporters Provider")
    exporters_def.secure = False
    exporters_def.gettext_domain = "plainbox-provider-exporters"
    exporters_def.location = os.path.join(
        get_plainbox_dir(), "impl/providers/exporters")
    return exporters_def
Ejemplo n.º 9
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.role: [MemberOfFieldValidator(FileRole.get_all_symbols())]
        }
Ejemplo n.º 10
0
    class Meta:

        name = N_('category')

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

        field_validators = {
            fields.name: [
                concrete_validators.translatable,
                concrete_validators.templateVariant,
                concrete_validators.present,
                concrete_validators.oneLine,
                concrete_validators.shortValue,
            ]
        }
Ejemplo n.º 11
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')),
            ]
        }
from plainbox.i18n import gettext_noop as N_
from plainbox.impl.applogic import get_all_exporter_names
from plainbox.impl.commands import PlainBoxCommand


@docstring(
    N_("""
    session management commands

    This command can be used to list, show and remove sessions owned by the
    current user.

    @EPILOG@

    Each session has a small amount of meta-data that is available for
    inspection. Each session has an application identifier (set by the
    application that created that session), a title, that is human readable
    piece of text that helps to distinguish sessions, and a set of flags.

    Flags are particularly useful for determining what is the overall state
    of any particular session. Two flags are standardized (other flags can be
    used by applications): incomplete and submitted. The 'incomplete' flag is
    removed after all desired jobs have been executed. The 'submitted' flag
    is set after a submission is made using any of the transport mechanisms.
    """))
class SessionCommand(PlainBoxCommand):
    def __init__(self, provider_loader):
        super().__init__()
        self.provider_loader = provider_loader

    def invoked(self, ns):
Ejemplo n.º 13
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.º 14
0
                    _("Successfully sent, server response"
                      ": {0}").format(result))


@docstring(
    # TRANSLATORS: please leave various options (both long and short forms),
    # environment variables and paths in their original form. Also keep the
    # special @EPILOG@ string. The first line of the translation is special and
    # is used as the help message. Please keep the pseudo-statement form and
    # don't finish the sentence with a dot. Pay extra attention to whitespace.
    # It must be correctly preserved or the result won't work. In particular
    # the leading whitespace *must* be preserved and *must* have the same
    # length on each line.
    N_("""
    submit test results to the Canonical certification website

    This command sends the XML results file to the Certification website.
    """))
class SubmitCommand(PlainBoxCommand):

    gettext_domain = "checkbox-ng"

    def __init__(self, config_loader):
        self.config = config_loader()

    def invoked(self, ns):
        return SubmitInvocation(ns).run()

    def register_parser(self, subparsers):
        parser = subparsers.add_parser(
            "submit",
Ejemplo n.º 15
0
    # special @EPILOG@ string. The first line of the translation is special and
    # is used as the help message. Please keep the pseudo-statement form and
    # don't finish the sentence with a dot. Pay extra attention to whitespace.
    # It must be correctly preserved or the result won't work. In particular
    # the leading whitespace *must* be preserved and *must* have the same
    # length on each line.
    N_("""
    create a new provider (directory)

    Creates a new provider from a built-in skeleton.

    @EPILOG@

    The name of the provider must follow the pattern ``YYYY.example.org:name``
    where ``YYYY`` is a four-digit year when the author of the provider owned
    the domain (here, ``example.org``) and ``name`` is arbitrary identifier
    that is managed by the owner of that domain. The identifier should be
    constrained to ASCII, digits and the dash character.

    This naming scheme allows anyone that ever owned a domain name to come up
    with non-clashing provider identifiers. Those identifiers are going to be
    used in fully qualified names of various objects.

    This command creates a new skeleton test provider for PlainBox. The
    generated content should be edited to fit a particular purpose.
    """))
class StartProviderCommand(PlainBoxCommand):

    def invoked(self, ns):
        return StartProviderInvocation(ns.name).run()

    def register_parser(self, subparsers):
Ejemplo n.º 16
0
    # the leading whitespace *must* be preserved and *must* have the same
    # length on each line.
    N_("""
    run qml job in standalone shell

    Runs specified file as it would be a plainbox' qml job.
    Returns 0 if job returned 'pass', 1 if job returned 'fail', or
    other value in case of an error.

    @EPILOG@

    General purpose of this command is to make development of qml-native jobs
    faster, by making it easier to test qml file(s) that constitute to job
    without resorting to installation of provider and running plainbox run.
    Typical approach to the development of new qml job would be as follows:

    - have an idea for a job

    - create a qml file in Ubuntu-SDK or Your Favourite Editor

    - hack on the file and iterate using qmlscene (or use plainbox-qml-shell
      immediately if you start with next point)

    - make it conformant to plainbox qml-native API described in CEP-5
      (calling test-done at the end)

    - copy qml file over to data dir of a provider and add a job unit to it

    """))
class QmlShellCommand(PlainBoxCommand):
    def register_parser(self, subparsers):
Ejemplo n.º 17
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.º 18
0
This module contains the user interface parts of the 'plainbox device' command.
"""
from logging import getLogger

from plainbox.i18n import docstring
from plainbox.i18n import gettext_noop as N_
from plainbox.impl.commands import PlainBoxCommand

logger = getLogger("plainbox.commands.device")


@docstring(
    N_("""
    device management commands

    This command can be used to show the device that plainbox is executing

    @EPILOG@

    TBD
    """))
class DeviceCommand(PlainBoxCommand):
    def invoked(self, ns):
        from plainbox.impl.commands.inv_device import DeviceInvocation
        return DeviceInvocation(ns).run()

    def register_parser(self, subparsers):
        parser = self.add_subcommand(subparsers)
        parser.prog = 'plainbox device'
Ejemplo n.º 19
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.º 20
0
    N_("""
    install this provider in the system

    This command installs the provider to the specified prefix.

    @EPILOG@

    Installation Layouts
    ====================

    There are two possible installation layouts: flat, perfect for keeping the
    whole provider in one directory, and unix, which is optimized for
    packaging and respecting the filesystem hierarchy.

    In both cases, a generated file is created at a fixed location:

        {prefix}/share/plainbox-providers-1/{provider.name}.provider

    This file is essential for plainbox to discover providers. It contains
    meta-data collected from the manage.py setup() call.

    For Packaging
    -------------

    System-wide installations should typically use `--prefix=/usr` coupled
    with `--layout=unix`. For packaging you will want to use the `--root=`
    argument to place all of the copied and generated files into your packaging
    system staging area. This will not affect generated content, which only
    respects the prefix argument.

    UNIX Layout
    -----------

    In the unix layout, following transformation is applied:

    @LAYOUT[unix]@

    Flat Layout
    -----------

    @LAYOUT[flat]@
    """))