def test_init_without_plugin_name(tmpdir):
        init.init(tmpdir.strpath, const.DIRECT_TYPE, "", const.UNIX_HOST_TYPE)

        result = plugin_util.validate_plugin_config_file(
            os.path.join(tmpdir.strpath, init.DEFAULT_PLUGIN_CONFIG_FILE),
            True)

        config = result.plugin_config_content

        # Validate that the plugin name is equal to plugin id
        assert config['name'] == config['id']
    def test_init_windows_plugin(tmpdir, plugin_name):
        init.init(tmpdir.strpath, const.DIRECT_TYPE, plugin_name,
                  const.WINDOWS_HOST_TYPE)
        result = plugin_util.validate_plugin_config_file(
            os.path.join(tmpdir.strpath, init.DEFAULT_PLUGIN_CONFIG_FILE),
            True)
        config = result.plugin_config_content

        # Validate that the host type is WINDOWS
        host_types = config['hostTypes']
        assert len(host_types) == 1
        assert host_types[0] == const.WINDOWS_HOST_TYPE
    def test_init(tmpdir, ingestion_strategy, host_type, schema_template,
                  plugin_name, format_entry_point_template):
        # Initialize an empty directory.
        init.init(tmpdir.strpath, ingestion_strategy, plugin_name, host_type)

        # Validate the config file is as we expect.
        result = plugin_util.validate_plugin_config_file(
            os.path.join(tmpdir.strpath, init.DEFAULT_PLUGIN_CONFIG_FILE),
            True)

        config = result.plugin_config_content

        assert config['hostTypes'] == [host_type]
        assert config['pluginType'] == ingestion_strategy
        assert config['name'] == plugin_name
        assert config['entryPoint'] == init.DEFAULT_ENTRY_POINT
        assert config['srcDir'] == init.DEFAULT_SRC_DIRECTORY
        assert config['schemaFile'] == init.DEFAULT_SCHEMA_FILE
        assert config['buildNumber'] == init.DEFAULT_BUILD_NUMBER

        # Validate the schema file is identical to the template.
        schema_file_path = os.path.join(tmpdir.strpath, config['schemaFile'])
        with open(schema_file_path, 'r') as f:
            schema = json.load(f)
            assert schema == schema_template

        # Rebuild the entry file name from the entry point in the config file.
        entry_module, _ = config['entryPoint'].split(':')
        entry_file = entry_module + '.py'

        # Validate the entry file is identical to the template.
        entry_file_path = os.path.join(tmpdir.strpath, config['srcDir'],
                                       entry_file)
        with open(entry_file_path, 'r') as f:
            contents = f.read()
            assert contents == format_entry_point_template(
                config['id'], ingestion_strategy, host_type)
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.')