Ejemplo n.º 1
0
 def test_get_src_dir_path_is_abs_fail():
     expected_message = "The path '{}' should be a relative path, but is " \
                        "not.".format('/absolute/src')
     with pytest.raises(exceptions.UserError) as err_info:
         file_util.get_src_dir_path('/absolute/config', '/absolute/src')
     message = err_info.value.message
     assert expected_message in message
Ejemplo n.º 2
0
    def test_get_src_dir_path_fail(tmpdir):
        test_file = os.path.join(tmpdir.strpath, 'test_file')
        expected_message = 'The path \'{}\' does not exist'.format(test_file)
        with pytest.raises(exceptions.UserError) as err_info:
            file_util.get_src_dir_path(test_file, test_file)

        message = err_info.value.message
        assert expected_message in message
Ejemplo n.º 3
0
 def test_get_src_dir_path_exists_fail():
     expected_path = os.path.join(os.getcwd(), 'fake', 'nonexistent', 'dir')
     expected_message = "The path '{}' does not exist.".format(
         expected_path)
     with pytest.raises(exceptions.UserError) as err_info:
         file_util.get_src_dir_path('fake/plugin_config', 'nonexistent/dir')
     message = err_info.value.message
     assert expected_message in message
Ejemplo n.º 4
0
 def test_get_src_dir_path_is_dir_fail(mock_existing_path,
                                       mock_relative_path):
     expected_path = os.path.join(os.getcwd(), 'fake', 'not', 'dir')
     expected_message = "The path '{}' should be a {} but is not.".format(
         expected_path, 'directory')
     with pytest.raises(exceptions.UserError) as err_info:
         file_util.get_src_dir_path('fake/plugin_config', 'not/dir')
     message = err_info.value.message
     assert expected_message in message
Ejemplo n.º 5
0
    def __run_validations(self):
        """
        Reads a plugin config file and validates the contents using a
        pre-defined schema. If validation is successful, tries to import
        the plugin module and validates the entry point specified.
        """
        logger.info('Reading plugin config file %s', self.__plugin_config)

        if self.__plugin_config_content is None:
            self.__plugin_config_content = self.__read_plugin_config_file()

        logger.debug('Validating plugin config file content : %s',
                     self.__plugin_config_content)
        self.__validate_plugin_config_content()

        if not self.__run_all_validations:
            logger.debug('Plugin config file schema validation is done')
            return

        src_dir = file_util.get_src_dir_path(
            self.__plugin_config, self.__plugin_config_content['srcDir'])

        logger.debug('Validating plugin entry point : %s',
                     self.__plugin_config_content['entryPoint'])
        self.__validate_plugin_entry_point(src_dir)
def get_plugin_manifest(plugin_config_file,
                        plugin_config_content,
                        stop_build,
                        skip_id_validation=False):
    """
    Validates the given plugin config content using a pre-defined schema.
    Plugin config file name is used to get the absolute path of plugin source
    directory. Returns a manifest which indicates method implemented in the
    plugin module.
    """
    validation_mode = (ValidationMode.ERROR
                       if stop_build else ValidationMode.WARNING)
    src_dir = file_util.get_src_dir_path(plugin_config_file,
                                         plugin_config_content['srcDir'])
    entry_point_module, entry_point_object = PluginValidator.split_entry_point(
        plugin_config_content['entryPoint'])
    plugin_type = plugin_config_content['pluginType']

    importer = PluginImporter(src_dir, entry_point_module, entry_point_object,
                              plugin_type, True)

    with validate_error_handler(plugin_config_file, validation_mode):
        importer.validate_plugin_module()

    return importer.result
Ejemplo n.º 7
0
    def test_get_src_dir_path_fail(mock_relative_path, mock_existing_path,
                                   mock_directory_path,
                                   plugin_config_file_path, src_dir_path):
        expected_plugin_root_dir = os.path.dirname(plugin_config_file_path)

        expected_plugin_root_dir = file_util.standardize_path(
            expected_plugin_root_dir)
        expected_src_dir = file_util.standardize_path(
            os.path.join(expected_plugin_root_dir, src_dir_path))

        expected_src_dir = os.path.join(expected_plugin_root_dir,
                                        expected_src_dir)

        expected_message = "The src directory {} is not a subdirectory of " \
                           "the plugin root at {}"\
            .format(expected_src_dir,
                    os.path.dirname(expected_plugin_root_dir))
        with pytest.raises(exceptions.UserError) as err_info:
            file_util.get_src_dir_path(plugin_config_file_path, src_dir_path)
        message = err_info.value.message
        assert expected_message in message
Ejemplo n.º 8
0
def get_plugin_importer(plugin_config_file):
    plugin_config_content = None
    with open(plugin_config_file, 'rb') as f:
        plugin_config_content = yaml.safe_load(f)

    src_dir = file_util.get_src_dir_path(plugin_config_file,
                                         plugin_config_content['srcDir'])
    entry_point_module, entry_point_object = plugin_validator.PluginValidator\
        .split_entry_point(plugin_config_content['entryPoint'])
    plugin_type = plugin_config_content['pluginType']

    return PluginImporter(src_dir, entry_point_module, entry_point_object,
                          plugin_type, True)
Ejemplo n.º 9
0
    def test_get_src_dir_path_relative(tmp_path):
        plugin_root = tmp_path / 'plugin'
        src_dir = plugin_root / 'src'
        plugin_root.mkdir()
        src_dir.mkdir()

        cwd = os.getcwd()
        try:
            os.chdir(tmp_path.as_posix())
            actual = file_util.get_src_dir_path('plugin/plugin_config.yml',
                                                'src')
        finally:
            os.chdir(cwd)

        assert actual == src_dir.as_posix()
Ejemplo n.º 10
0
def build(plugin_config, upload_artifact, generate_only, skip_id_validation):
    """This builds the plugin using the configurations provided in config yaml
    file provided as input. It reads schemas and source code from the files
    given in yaml file, generates an encoded string of zip of source code,
    prepares plugin json output file that can be used by upload command later.

    Args:
        plugin_config: Plugin config file used for building plugin.
        upload_artifact: The file to which output of build  is written to.
        generate_only: Only generate python classes from schema definitions.
        skip_id_validation: Skip validation of the plugin id.
    """
    logger.debug(
        "Build parameters include plugin_config: %s, upload_artifact: %s,"
        " generate_only: %s",
        plugin_config,
        upload_artifact,
        generate_only,
    )

    # Read content of the plugin config  file provided and perform validations
    logger.info("Reading and validating plugin config file %s", plugin_config)
    try:
        result = plugin_util.read_and_validate_plugin_config_file(
            plugin_config, not generate_only, False, skip_id_validation)
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    plugin_config_content = result.plugin_config_content
    logger.debug("plugin config file content is : %s",
                 result.plugin_config_content)

    schema_file = plugin_util.get_schema_file_path(
        plugin_config, plugin_config_content["schemaFile"])

    # Read schemas from the file provided in the config and validate them
    logger.info("Reading and validating schemas from %s", schema_file)

    try:
        result = plugin_util.read_and_validate_schema_file(
            schema_file, not generate_only)
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    schemas = result.plugin_schemas
    logger.debug("schemas found: %s", schemas)

    # Resolve the paths for source directory and schema file
    src_dir = file_util.get_src_dir_path(plugin_config,
                                         plugin_config_content["srcDir"])
    logger.debug("Source directory path resolved is %s", src_dir)

    #
    # Call directly into codegen to generate the python classes and make sure
    # the ones we zip up are up to date with the schemas.
    #
    try:
        codegen.generate_python(
            plugin_config_content["name"],
            src_dir,
            os.path.dirname(plugin_config),
            schemas,
        )
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    if generate_only:
        #
        # If the generate_only flag is set then just return after generation
        # has happened.
        #
        logger.info("Generating python code only. Skipping artifact build.")
        return

    #
    # Validate the plugin config content by importing the module
    # and check the entry point as well. Returns a manifest on
    # successful validation.
    #
    try:
        result = plugin_util.get_plugin_manifest(plugin_config,
                                                 plugin_config_content,
                                                 not generate_only,
                                                 skip_id_validation)
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    plugin_manifest = {}
    if result:
        plugin_manifest = result.plugin_manifest
        if result.warnings:
            warning_msg = util_classes.MessageUtils.warning_msg(
                result.warnings)
            logger.warn("{}\n{} Warning(s). {} Error(s).".format(
                warning_msg, len(result.warnings["warning"]), 0))

    # Prepare the output artifact.
    try:
        plugin_output = prepare_upload_artifact(plugin_config_content, src_dir,
                                                schemas, plugin_manifest)
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    # Write it to upload_artifact as json.
    try:
        generate_upload_artifact(upload_artifact, plugin_output)
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    logger.info("Successfully generated artifact file at %s.", upload_artifact)

    logger.warn("\nBUILD SUCCESSFUL.")
Ejemplo n.º 11
0
 def test_get_src_dir_path(tmpdir):
     test_file = os.path.join(tmpdir.strpath, 'test_file')
     src_dir = file_util.get_src_dir_path(test_file, tmpdir.strpath)
     assert src_dir == tmpdir.strpath
Ejemplo n.º 12
0
 def test_get_src_dir_path_success(mock_relative_path, mock_existing_path,
                                   mock_directory_path,
                                   plugin_config_file_path, src_dir_path):
     file_util.get_src_dir_path(plugin_config_file_path, src_dir_path)
Ejemplo n.º 13
0
def build(plugin_config,
          upload_artifact,
          generate_only,
          skip_id_validation,
          local_vsdk_root=None):
    """This builds the plugin using the configurations provided in config yaml
    file provided as input. It reads schemas and source code from the files
    given in yaml file, generates an encoded string of zip of source code,
    prepares plugin json output file that can be used by upload command later.

    Args:
        plugin_config: Plugin config file used for building plugin.
        upload_artifact: The file to which output of build  is written to.
        generate_only: Only generate python classes from schema definitions.
        skip_id_validation: Skip validation of the plugin id.
        local_vsdk_root: The local path to the root of the Virtualization SDK
            repository.
    """
    logger.debug(
        'Build parameters include plugin_config: %s, upload_artifact: %s,'
        ' generate_only: %s', plugin_config, upload_artifact, generate_only)

    if local_vsdk_root:
        local_vsdk_root = os.path.expanduser(local_vsdk_root)

    # Read content of the plugin config  file provided and perform validations
    logger.info('Validating plugin config file %s', plugin_config)
    try:
        result = plugin_util.validate_plugin_config_file(
            plugin_config, not generate_only, skip_id_validation)
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    plugin_config_content = result.plugin_config_content
    logger.debug('plugin config file content is : %s',
                 result.plugin_config_content)

    schema_file = plugin_util.get_schema_file_path(
        plugin_config, plugin_config_content['schemaFile'])

    # Read schemas from the file provided in the config and validate them
    logger.info('Validating schemas from %s', schema_file)

    try:
        result = plugin_util.validate_schema_file(schema_file,
                                                  not generate_only)
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    schemas = result.plugin_schemas
    logger.debug('schemas found: %s', schemas)

    # Resolve the paths for source directory and schema file
    src_dir = file_util.get_src_dir_path(plugin_config,
                                         plugin_config_content['srcDir'])
    logger.debug('Source directory path resolved is %s', src_dir)

    #
    # Call directly into codegen to generate the python classes and make sure
    # the ones we zip up are up to date with the schemas.
    #
    try:
        codegen.generate_python(plugin_config_content['name'], src_dir,
                                os.path.dirname(plugin_config), schemas)
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    if generate_only:
        #
        # If the generate_only flag is set then just return after generation
        # has happened.
        #
        logger.info('Generating python code only. Skipping artifact build.')
        return

    #
    # Validate the plugin config content by importing the module
    # and check the entry point as well. Returns a manifest on
    # successful validation.
    #
    try:
        result = plugin_util.get_plugin_manifest(plugin_config,
                                                 plugin_config_content,
                                                 not generate_only,
                                                 skip_id_validation)
    except (exceptions.UserError, exceptions.SDKToolingError) as err:
        raise exceptions.BuildFailedError(err)

    plugin_manifest = {}
    if result:
        plugin_manifest = result.plugin_manifest

    #
    # Setup a build directory for the plugin in its root. Dependencies are
    # packaged with the plugin and should not be installed into the original
    # source directory.
    #
    root = os.path.dirname(plugin_config)
    build_dir = os.path.join(root, BUILD_DIR_NAME)
    build_src_dir = os.path.join(build_dir, os.path.basename(src_dir))

    # Copy everything from the source directory into the build directory.
    file_util.clean_copy(src_dir, build_src_dir)

    # Install dependencies in the plugin's source root in the build directory.
    plugin_dependency_util.install_deps(build_src_dir,
                                        local_vsdk_root=local_vsdk_root)

    # Prepare the output artifact.
    try:
        plugin_output = prepare_upload_artifact(plugin_config_content,
                                                build_src_dir, schemas,
                                                plugin_manifest)
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    # Write it to upload_artifact as json.
    try:
        generate_upload_artifact(upload_artifact, plugin_output)
    except exceptions.UserError as err:
        raise exceptions.BuildFailedError(err)

    logger.info('Successfully generated artifact file at %s.', upload_artifact)

    logger.warn('\nBUILD SUCCESSFUL.')