Exemple #1
0
def _install_dependency(dependency_name: str, dependency: Dependency):
    click.echo("Installing {}...".format(pprint.pformat(dependency_name)))
    try:
        index = dependency.get("index", None)
        git_url = dependency.get("git", None)
        revision = dependency.get("ref", "")
        version_constraint = dependency.get("version", "")
        command = [sys.executable, "-m", "pip", "install"]
        if git_url is not None:
            command += ["-i", index] if index is not None else []
            command += [
                "git+" + git_url + "@" + revision + "#egg=" + dependency_name
            ]
        else:
            command += ["-i", index] if index is not None else []
            command += [dependency_name + version_constraint]
        logger.debug("Calling '{}'".format(" ".join(command)))
        return_code = _run_install_subprocess(command)
        if return_code == 1:
            # try a second time
            return_code = _run_install_subprocess(command)
        assert return_code == 0, "Return code != 0."
    except Exception as e:
        raise AEAException(
            "An error occurred while installing {}, {}: {}".format(
                dependency_name, dependency, str(e)))
Exemple #2
0
def get_latest_public_id_mixed(
    ctx: Context,
    item_type: str,
    item_public_id: PublicId,
    aea_version: Optional[str] = None,
) -> PublicId:
    """
    Get latest public id of the message, mixed mode.

    That is, give priority to local registry, and fall back to remote registry
    in case of failure.

    :param ctx: the CLI context.
    :param item_type: the item type.
    :param item_public_id: the item public id.
    :param aea_version: the AEA version constraint, or None
    :return: the path to the found package.
    """
    try:
        _, item_config = find_item_locally(ctx, item_type, item_public_id)
        latest_item_public_id = item_config.public_id
    except click.ClickException:
        logger.debug(
            "Get latest public id from local registry failed, trying remote registry..."
        )
        # the following might raise exception, but we don't catch it this time
        package_meta = get_package_meta(
            item_type, item_public_id, aea_version=aea_version
        )
        latest_item_public_id = PublicId.from_str(cast(str, package_meta["public_id"]))
    return latest_item_public_id
Exemple #3
0
def fetch_item_mixed(
    ctx: Context,
    item_type: str,
    item_public_id: PublicId,
    dest_path: str,
) -> Path:
    """
    Find item, mixed mode.

    That is, give priority to local registry, and fall back to remote registry
    in case of failure.

    :param ctx: the CLI context.
    :param item_type: the item type.
    :param item_public_id: the item public id.
    :param dest_path: the path to the destination.
    :return: the path to the found package.
    """
    try:
        package_path = find_item_locally_or_distributed(
            ctx, item_type, item_public_id, dest_path)
    except click.ClickException as e:
        logger.debug(
            f"Fetch from local registry failed (reason={str(e)}), trying remote registry..."
        )
        # the following might raise exception, but we don't catch it this time
        package_path = fetch_package(item_type,
                                     public_id=item_public_id,
                                     cwd=ctx.cwd,
                                     dest=dest_path)
    return package_path
Exemple #4
0
def remove_item(ctx: Context, item_type: str, item_id: PublicId) -> None:
    """
    Remove an item from the configuration file and agent, given the public id.

    :param ctx: Context object.
    :param item_type: type of item.
    :param item_id: item public ID.

    :return: None
    :raises ClickException: if some error occures.
    """
    item_name = item_id.name
    item_type_plural = "{}s".format(item_type)
    existing_item_ids = getattr(ctx.agent_config, item_type_plural)
    existing_items_name_to_ids = {
        public_id.name: public_id
        for public_id in existing_item_ids
    }

    agent_name = ctx.agent_config.agent_name
    click.echo(
        "Removing {item_type} '{item_name}' from the agent '{agent_name}'...".
        format(agent_name=agent_name, item_type=item_type,
               item_name=item_name))

    if (item_id not in existing_items_name_to_ids.keys()
            and item_id not in existing_item_ids):
        raise click.ClickException("The {} '{}' is not supported.".format(
            item_type, item_id))

    item_folder = Path(ctx.cwd, "vendor", item_id.author, item_type_plural,
                       item_name)
    if not item_folder.exists():
        # check if it is present in custom packages.
        item_folder = Path(ctx.cwd, item_type_plural, item_name)
        if not item_folder.exists():
            raise click.ClickException("{} {} not found. Aborting.".format(
                item_type.title(), item_name))
        elif (item_folder.exists() and not ctx.agent_config.author
              == item_id.author):  # pragma: no cover
            raise click.ClickException(
                "{} {} author is different from {} agent author. "
                "Please fix the author field.".format(item_name, item_type,
                                                      agent_name))
        else:
            logger.debug("Removing local {} {}.".format(
                item_type, item_name))  # pragma: no cover

    try:
        shutil.rmtree(item_folder)
    except BaseException:
        raise click.ClickException("An error occurred.")

    # removing the protocol to the configurations.
    item_public_id = existing_items_name_to_ids[item_name]
    logger.debug("Removing the {} from {}".format(item_type,
                                                  DEFAULT_AEA_CONFIG_FILE))
    existing_item_ids.remove(item_public_id)
    with open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w") as f:
        ctx.agent_loader.dump(ctx.agent_config, f)
def copy_package_directory(
    ctx: Context,
    package_path: Path,
    item_type: str,
    item_name: str,
    author_name: str,
    dest: str,
) -> Path:
    """
     Copy a package directory to the agent vendor resources.

    :param ctx: the CLI context .
    :param package_path: the path to the package to be added.
    :param item_type: the type of the package.
    :param item_name: the name of the package.
    :param author_name: the author of the package.

    :return: copied folder target path.
    :raises SystemExit: if the copy raises an exception.
    """
    # copy the item package into the agent's supported packages.
    item_type_plural = item_type + "s"
    src = str(package_path.absolute())
    logger.debug("Copying {} modules. src={} dst={}".format(item_type, src, dest))
    try:
        shutil.copytree(src, dest)
    except Exception as e:
        raise click.ClickException(str(e))

    Path(ctx.cwd, "vendor", author_name, item_type_plural, "__init__.py").touch()
    return Path(dest)
def _process_connection(
    project_directory: str,
    agent_config_manager: AgentConfigManager,
    cert_requests: List[CertRequest],
    connection_id: PublicId,
):

    if len(cert_requests) == 0:
        logger.debug("No certificates to process.")
        return

    logger.debug(f"Processing connection '{connection_id}'...")
    for cert_request in cert_requests:
        click.echo(
            f"Issuing certificate '{cert_request.identifier}' for connection {connection_id}..."
        )
        _process_certificate(
            project_directory,
            agent_config_manager.agent_config,
            cert_request,
            connection_id,
        )
        click.echo(
            f"Dumped certificate '{cert_request.identifier}' in '{cert_request.save_path}' for connection {connection_id}."
        )
Exemple #7
0
def search(click_context, local):
    """Search for components in the registry.

    If called from an agent directory, it will check

    E.g.

        aea search connections
        aea search --local skills
    """
    ctx = cast(Context, click_context.obj)
    if local:
        ctx.set_config("is_local", True)
        # if we are in an agent directory, try to load the configuration file.
        # otherwise, use the default path (i.e. 'packages/' in the current directory.)
        try:
            try_to_load_agent_config(ctx, is_exit_on_except=False)
            # path = Path(DEFAULT_AEA_CONFIG_FILE)
            # fp = open(str(path), mode="r", encoding="utf-8")
            # agent_config = ctx.agent_loader.load(fp)
            registry_directory = ctx.agent_config.registry_path
        except Exception:
            registry_directory = os.path.join(ctx.cwd, DEFAULT_REGISTRY_PATH)

        ctx.set_config("registry_directory", registry_directory)
        logger.debug("Using registry {}".format(registry_directory))
Exemple #8
0
def publish_agent(ctx: Context):
    """Publish an agent."""
    try_to_load_agent_config(ctx)
    check_is_author_logged_in(ctx.agent_config.author)

    name = ctx.agent_config.agent_name
    config_file_source_path = os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE)
    output_tar = os.path.join(ctx.cwd, "{}.tar.gz".format(name))

    with tempfile.TemporaryDirectory() as temp_dir:
        package_dir = os.path.join(temp_dir, name)
        os.makedirs(package_dir)
        config_file_target_path = os.path.join(package_dir, DEFAULT_AEA_CONFIG_FILE)
        shutil.copy(config_file_source_path, config_file_target_path)

        _compress(output_tar, package_dir)

    data = {
        "name": name,
        "description": ctx.agent_config.description,
        "version": ctx.agent_config.version,
        "connections": ctx.agent_config.connections,
        "contracts": ctx.agent_config.contracts,
        "protocols": ctx.agent_config.protocols,
        "skills": ctx.agent_config.skills,
    }

    path = "/agents/create"
    logger.debug("Publishing agent {} to Registry ...".format(name))
    resp = request_api("POST", path, data=data, is_auth=True, filepath=output_tar)
    click.echo(
        "Successfully published agent {} to the Registry. Public ID: {}".format(
            name, resp["public_id"]
        )
    )
Exemple #9
0
def _generate_full_mode(
    ctx: Context,
    protocol_generator: ProtocolGenerator,
    protocol_spec: ProtocolSpecification,
    existing_id_list: Set[PublicId],
    language: str,
) -> None:
    """Generate a protocol in 'full' mode, and add it to the configuration file and agent."""
    try:
        warning_message = protocol_generator.generate(protobuf_only=False,
                                                      language=language)
        if warning_message is not None:
            click.echo(warning_message)

        # Add the item to the configurations
        logger.debug("Registering the {} into {}".format(
            PROTOCOL, DEFAULT_AEA_CONFIG_FILE))
        existing_id_list.add(
            PublicId(protocol_spec.author, protocol_spec.name,
                     protocol_spec.version))
        ctx.agent_loader.dump(
            ctx.agent_config,
            open_file(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w"),
        )
    except FileExistsError:
        raise click.ClickException(  # pragma: no cover
            "A {} with this name already exists. Please choose a different name and try again."
            .format(PROTOCOL))
    except Exception as e:
        raise click.ClickException(
            "Protocol is NOT generated. The following error happened while generating the protocol:\n"
            + str(e))
    fingerprint_item(ctx, PROTOCOL, protocol_spec.public_id)
Exemple #10
0
def _add_protocols(click_context, protocols: Collection[PublicId]):
    ctx = cast(Context, click_context.obj)
    # check for dependencies not yet added, and add them.
    for protocol_public_id in protocols:
        if protocol_public_id not in ctx.agent_config.protocols:
            logger.debug(
                "Adding protocol '{}' to the agent...".format(protocol_public_id)
            )
            _add_item(click_context, "protocol", protocol_public_id)
Exemple #11
0
 def _remove_from_config(self) -> None:
     """Remove item from agent config."""
     current_item = self.get_current_item()
     logger.debug("Removing the {} from {}".format(self.item_type,
                                                   DEFAULT_AEA_CONFIG_FILE))
     self.agent_items.remove(current_item)
     self.agent_config.component_configurations.pop(
         ComponentId(self.item_type, current_item), None)
     self.ctx.dump_agent_config()
Exemple #12
0
def launch(click_context, agents: List[str], multithreaded: bool):
    """Launch many agents at the same time."""
    agents_directories = list(map(Path, list(OrderedDict.fromkeys(agents))))
    if multithreaded:
        failed = _launch_threads(click_context, agents_directories)
    else:
        failed = _launch_subprocesses(click_context, agents_directories)
    logger.debug(f"Exit cli. code: {failed}")
    sys.exit(failed)
Exemple #13
0
    def set_config(self, key, value) -> None:
        """
        Set a config.

        :param key: the key for the configuration.
        :param value: the value associated with the key.
        :return: None
        """
        self.config[key] = value
        logger.debug("  config[{}] = {}".format(key, value))
Exemple #14
0
def fetch_package(obj_type: str, public_id: PublicId, cwd: str,
                  dest: str) -> Path:
    """
    Fetch a package (connection/contract/protocol/skill) from Registry.

    :param obj_type: str type of object you want to fetch:
        'connection', 'protocol', 'skill'
    :param public_id: str public ID of object.
    :param cwd: str path to current working directory.

    :return: package path
    """
    logger.debug("Fetching {obj_type} {public_id} from Registry...".format(
        public_id=public_id, obj_type=obj_type))

    logger.debug("Downloading {obj_type} {public_id}...".format(
        public_id=public_id, obj_type=obj_type))
    package_meta = get_package_meta(obj_type, public_id)
    file_url = package_meta["file"]
    filepath = download_file(file_url, cwd)

    # next code line is needed because the items are stored in tarball packages as folders
    dest = os.path.split(dest)[0]
    logger.debug("Extracting {obj_type} {public_id}...".format(
        public_id=public_id, obj_type=obj_type))
    extract(filepath, dest)
    logger.debug("Successfully fetched {obj_type} '{public_id}'.".format(
        public_id=public_id, obj_type=obj_type))
    package_path = os.path.join(dest, public_id.name)
    return Path(package_path)
Exemple #15
0
def publish_agent(ctx: Context) -> None:
    """Publish an agent."""
    try_to_load_agent_config(ctx)
    check_is_author_logged_in(ctx.agent_config.author)

    name = ctx.agent_config.agent_name
    config_file_source_path = os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE)
    readme_source_path = os.path.join(ctx.cwd, DEFAULT_README_FILE)
    output_tar = os.path.join(ctx.cwd, "{}.tar.gz".format(name))

    with tempfile.TemporaryDirectory() as temp_dir:
        package_dir = os.path.join(temp_dir, name)
        os.makedirs(package_dir)
        config_file_target_path = os.path.join(package_dir, DEFAULT_AEA_CONFIG_FILE)
        shutil.copy(config_file_source_path, config_file_target_path)
        if is_readme_present(readme_source_path):
            readme_file_target_path = os.path.join(package_dir, DEFAULT_README_FILE)
            shutil.copy(readme_source_path, readme_file_target_path)

        _compress(output_tar, package_dir)

    data = {
        "name": name,
        "description": ctx.agent_config.description,
        "version": ctx.agent_config.version,
        CONNECTIONS: ctx.agent_config.connections,
        CONTRACTS: ctx.agent_config.contracts,
        PROTOCOLS: ctx.agent_config.protocols,
        SKILLS: ctx.agent_config.skills,
    }

    files = {}
    try:
        files["file"] = open(output_tar, "rb")
        if is_readme_present(readme_source_path):
            files["readme"] = open(readme_source_path, "rb")
        path = "/agents/create"
        logger.debug("Publishing agent {} to Registry ...".format(name))
        resp = cast(
            JSONLike, request_api("POST", path, data=data, is_auth=True, files=files)
        )
    finally:
        for fd in files.values():
            fd.close()
    click.echo(
        "Successfully published agent {} to the Registry. Public ID: {}".format(
            name, resp["public_id"]
        )
    )
Exemple #16
0
def install(click_context, requirement: Optional[str]):
    """Install the dependencies."""
    ctx = cast(Context, click_context.obj)

    try:
        if requirement:
            logger.debug("Installing the dependencies in '{}'...".format(requirement))
            _install_from_requirement(requirement)
        else:
            logger.debug("Installing all the dependencies...")
            dependencies = ctx.get_dependencies()
            for name, d in dependencies.items():
                _install_dependency(name, d)
    except AEAException as e:
        raise click.ClickException(str(e))
Exemple #17
0
def _scaffold_non_package_item(ctx: Context, item_type: str, type_name: str,
                               class_name: str, aea_dir: str) -> None:
    """
    Scaffold a non-package item (e.g. decision maker handler, or error handler).

    :param ctx: the CLI context.
    :param item_type: the item type (e.g. 'decision_maker_handler')
    :param type_name: the type name (e.g. "decision maker")
    :param class_name: the class name (e.g. "DecisionMakerHandler")
    :param aea_dir: the AEA directory that contains the scaffold module
    :return: None
    """
    existing_item = getattr(ctx.agent_config, item_type)
    if existing_item != {}:
        raise click.ClickException(
            f"A {type_name} specification already exists. Aborting...")

    dest = Path(f"{item_type}.py")
    agent_name = ctx.agent_config.agent_name
    click.echo(f"Adding {type_name} scaffold to the agent '{agent_name}'...")
    # create the file name
    dotted_path = f".{item_type}{DOTTED_PATH_MODULE_ELEMENT_SEPARATOR}{class_name}"
    try:
        # copy the item package into the agent project.
        src = Path(os.path.join(AEA_DIR, aea_dir, "scaffold.py"))
        logger.debug(f"Copying {type_name}. src={src} dst={dest}")
        shutil.copyfile(src, dest)

        # add the item to the configurations.
        logger.debug(
            f"Registering the {type_name} into {DEFAULT_AEA_CONFIG_FILE}")
        setattr(
            ctx.agent_config,
            item_type,
            {
                "dotted_path": str(dotted_path),
                "file_path": str(os.path.join(".", dest)),
            },
        )
        ctx.agent_loader.dump(
            ctx.agent_config,
            open_file(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w"),
        )

    except Exception as e:
        os.remove(dest)
        raise click.ClickException(str(e))
Exemple #18
0
def _launch_agents(click_context: click.core.Context, agents: List[str],
                   multithreaded: bool) -> None:
    """
    Run multiple agents.

    :param click_context: click context object.
    :param agents: agents names.
    :param multithreaded: bool flag to run as multithreads.

    :return: None.
    """
    agents_directories = list(map(Path, list(OrderedDict.fromkeys(agents))))
    mode = "threaded" if multithreaded else "multiprocess"
    ctx = cast(Context, click_context.obj)

    launcher = AEALauncher(
        agent_dirs=agents_directories,
        mode=mode,
        fail_policy=ExecutorExceptionPolicies.log_only,
        log_level=ctx.verbosity,
    )

    try:
        """
        run in threaded mode and wait for thread finished cause issue with python 3.6/3.7 on windows
        probably keyboard interrupt exception gets lost in executor pool or in asyncio module
        """
        launcher.start(threaded=True)
        launcher.try_join_thread()
    except KeyboardInterrupt:
        logger.info("Keyboard interrupt detected.")
    finally:
        timeout: Optional[float] = None
        if os.name == "nt":
            # Windows bug: https://bugs.python.org/issue21822
            timeout = 0  # pragma: nocover
        launcher.stop(timeout)

    for agent in launcher.failed:
        logger.info(f"Agent {agent} terminated with exit code 1")

    for agent in launcher.not_failed:
        logger.info(f"Agent {agent} terminated with exit code 0")

    logger.debug(f"Exit cli. code: {launcher.num_failed}")
    sys.exit(1 if launcher.num_failed > 0 else 0)
Exemple #19
0
def push_item(ctx: Context, item_type: str, item_id: PublicId) -> None:
    """
    Push item to the Registry.

    :param item_type: str type of item (connection/protocol/skill).
    :param item_id: str item name.

    :return: None
    """
    item_type_plural = item_type + "s"

    items_folder = os.path.join(ctx.cwd, item_type_plural)
    item_path = os.path.join(items_folder, item_id.name)

    item_config_filepath = os.path.join(item_path, "{}.yaml".format(item_type))
    logger.debug("Reading {} {} config ...".format(item_id.name, item_type))
    item_config = load_yaml(item_config_filepath)
    check_is_author_logged_in(item_config["author"])

    logger.debug("Searching for {} {} in {} ...".format(
        item_id.name, item_type, items_folder))
    if not os.path.exists(item_path):
        raise click.ClickException(
            '{} "{}" not found  in {}. Make sure you run push command '
            "from a correct folder.".format(item_type.title(), item_id.name,
                                            items_folder))

    output_filename = "{}.tar.gz".format(item_id.name)
    logger.debug("Compressing {} {} to {} ...".format(item_id.name, item_type,
                                                      output_filename))
    _compress_dir(output_filename, item_path)
    output_filepath = os.path.join(ctx.cwd, output_filename)

    data = {
        "name": item_id.name,
        "description": item_config["description"],
        "version": item_config["version"],
    }

    # dependencies
    for key in ["connections", "contracts", "protocols", "skills"]:
        deps_list = item_config.get(key)
        if deps_list:
            data.update({key: deps_list})

    path = "/{}/create".format(item_type_plural)
    logger.debug("Pushing {} {} to Registry ...".format(
        item_id.name, item_type))
    resp = request_api("POST",
                       path,
                       data=data,
                       is_auth=True,
                       filepath=output_filepath)
    click.echo(
        "Successfully pushed {} {} to the Registry. Public ID: {}".format(
            item_type, item_id.name, resp["public_id"]))
def register_item(ctx: Context, item_type: str,
                  item_public_id: PublicId) -> None:
    """
    Register item in agent configuration.

    :param ctx: click context object.
    :param item_type: type of item.
    :param item_public_id: PublicId of item.

    :return: None.
    """
    logger.debug("Registering the {} into {}".format(item_type,
                                                     DEFAULT_AEA_CONFIG_FILE))
    supported_items = get_items(ctx.agent_config, item_type)
    supported_items.add(item_public_id)
    with open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w") as fp:
        ctx.agent_loader.dump(ctx.agent_config, fp)
Exemple #21
0
def _scaffold_dm_handler(click_context):
    """Add a scaffolded decision maker handler to the project and configuration."""

    ctx = cast(Context, click_context.obj)
    existing_dm_handler = getattr(ctx.agent_config, "decision_maker_handler")

    # check if we already have a decision maker in the project
    if existing_dm_handler != {}:
        raise click.ClickException(
            "A decision maker handler specification already exists. Aborting..."
        )

    try:
        agent_name = ctx.agent_config.agent_name
        click.echo(
            "Adding decision maker scaffold to the agent '{}'...".format(
                agent_name))

        # create the file name
        dest = Path("decision_maker.py")
        dotted_path = ".decision_maker::DecisionMakerHandler"

        # copy the item package into the agent project.
        src = Path(os.path.join(AEA_DIR, "decision_maker", "scaffold.py"))
        logger.debug("Copying decision maker. src={} dst={}".format(src, dest))
        shutil.copyfile(src, dest)

        # add the item to the configurations.
        logger.debug("Registering the decision_maker into {}".format(
            DEFAULT_AEA_CONFIG_FILE))
        ctx.agent_config.decision_maker_handler = {
            "dotted_path": str(dotted_path),
            "file_path": str(os.path.join(".", dest)),
        }
        ctx.agent_loader.dump(
            ctx.agent_config,
            open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w"))

    except Exception as e:
        os.remove(dest)
        raise click.ClickException(str(e))
Exemple #22
0
def setup_search_ctx(ctx: Context, local: bool) -> None:
    """
    Set up search command.

    :param click_context: click context object.
    :param local: bool flag for local search.

    :return: None.
    """
    if local:
        ctx.set_config("is_local", True)
        # if we are in an agent directory, try to load the configuration file.
        # otherwise, use the default path (i.e. 'packages/' in the current directory.)
        try:
            try_to_load_agent_config(ctx, is_exit_on_except=False)
            registry_directory = ctx.agent_config.registry_path
        except Exception:  # pylint: disable=broad-except
            registry_directory = os.path.join(ctx.cwd, DEFAULT_REGISTRY_PATH)

        ctx.set_config("registry_directory", registry_directory)
        logger.debug("Using registry {}".format(registry_directory))
def copy_package_directory(src: Path, dst: str) -> Path:
    """
     Copy a package directory to the agent vendor resources.

    :param src: source path to the package to be added.
    :param dst: str package destenation path.

    :return: copied folder target path.
    :raises SystemExit: if the copy raises an exception.
    """
    # copy the item package into the agent's supported packages.
    src_path = str(src.absolute())
    logger.debug("Copying modules. src={} dst={}".format(src_path, dst))
    try:
        shutil.copytree(src_path, dst)
    except Exception as e:
        raise click.ClickException(str(e))

    items_folder = os.path.split(dst)[0]
    Path(items_folder, "__init__.py").touch()
    return Path(dst)
Exemple #24
0
def fetch_package(obj_type: str, public_id: PublicId, cwd: str,
                  dest: str) -> Path:
    """
    Fetch connection/protocol/skill from Registry.

    :param obj_type: str type of object you want to fetch:
        'connection', 'protocol', 'skill'
    :param public_id: str public ID of object.
    :param cwd: str path to current working directory.

    :return: package path
    """
    logger.debug("Fetching {obj_type} {public_id} from Registry...".format(
        public_id=public_id, obj_type=obj_type))
    author, name, version = public_id.author, public_id.name, public_id.version
    item_type_plural = obj_type + "s"  # used for API and folder paths

    api_path = "/{}/{}/{}/{}".format(item_type_plural, author, name, version)
    resp = request_api("GET", api_path)
    file_url = resp["file"]

    logger.debug("Downloading {obj_type} {public_id}...".format(
        public_id=public_id, obj_type=obj_type))
    filepath = download_file(file_url, cwd)

    # next code line is needed because the items are stored in tarball packages as folders
    dest = os.path.split(dest)[
        0]  # TODO: replace this hotfix with a proper solution
    logger.debug("Extracting {obj_type} {public_id}...".format(
        public_id=public_id, obj_type=obj_type))
    extract(filepath, dest)
    click.echo("Successfully fetched {obj_type}: {public_id}.".format(
        public_id=public_id, obj_type=obj_type))
    package_path = os.path.join(dest, public_id.name)
    return Path(package_path)
Exemple #25
0
def _process_connection(
    path_prefix: str,
    agent_config_manager: AgentConfigManager,
    cert_requests: List[CertRequest],
    connection_id: PublicId,
) -> None:

    if len(cert_requests) == 0:
        logger.debug("No certificates to process.")
        return

    logger.debug(f"Processing connection '{connection_id}'...")
    for cert_request in cert_requests:
        click.echo(
            f"Issuing certificate '{cert_request.identifier}' for connection {connection_id}..."
        )
        _process_certificate(
            path_prefix,
            agent_config_manager.agent_config,
            cert_request,
            connection_id,
        )
Exemple #26
0
def do_install(ctx: Context, requirement: Optional[str] = None) -> None:
    """
    Install necessary dependencies.

    :param ctx: context object.
    :param requirement: optional str requirement.

    :return: None
    :raises: ClickException if AEAException occurres.
    """
    try:
        if requirement:
            logger.debug(
                "Installing the dependencies in '{}'...".format(requirement))
            _install_from_requirement(requirement)
        else:
            logger.debug("Installing all the dependencies...")
            dependencies = ctx.get_dependencies()
            for name, d in dependencies.items():
                _install_dependency(name, d)
    except AEAException as e:
        raise click.ClickException(str(e))
Exemple #27
0
def fetch_mixed(
    ctx: Context,
    public_id: PublicId,
    alias: Optional[str] = None,
    target_dir: Optional[str] = None,
) -> None:
    """
    Fetch an agent in mixed mode.

    :param ctx: the Context.
    :param public_id: the public id.
    :param alias: the alias to the agent.
    :param target_dir: the target directory.
    :return: None
    """
    try:
        fetch_agent_locally(ctx, public_id, alias=alias, target_dir=target_dir)
    except click.ClickException as e:
        logger.debug(
            f"Fetch from local registry failed (reason={str(e)}), trying remote registry..."
        )
        fetch_agent(ctx, public_id, alias=alias, target_dir=target_dir)
Exemple #28
0
def _launch_agents(click_context: click.core.Context, agents: List[str],
                   multithreaded: bool) -> None:
    """
    Run multiple agents.

    :param click_context: click context object.
    :param agents: agents names.
    :param multithreaded: bool flag to run as multithreads.

    :return: None.
    """
    agents_directories = list(map(Path, list(OrderedDict.fromkeys(agents))))
    try:
        if multithreaded:
            failed = _launch_threads(agents_directories)
        else:
            failed = _launch_subprocesses(click_context, agents_directories)
    except BaseException:  # pragma: no cover
        logger.exception("Exception in launch agents.")
        failed = -1
    finally:
        logger.debug(f"Exit cli. code: {failed}")
        sys.exit(failed)
Exemple #29
0
def _setup_package_folder(path: Path):
    """Set a package folder up."""
    path.mkdir(exist_ok=False)
    init_module = path / "__init__.py"
    logger.debug("Creating {}".format(init_module))
    Path(init_module).touch(exist_ok=False)
Exemple #30
0
def _generate_item(click_context, item_type, specification_path):
    """Generate an item based on a specification and add it to the configuration file and agent."""
    # check protocol buffer compiler is installed
    ctx = cast(Context, click_context.obj)
    res = shutil.which("protoc")
    if res is None:
        raise click.ClickException(
            "Please install protocol buffer first! See the following link: https://developers.google.com/protocol-buffers/"
        )

    # check black code formatter is installed
    res = shutil.which("black")
    if res is None:
        raise click.ClickException(
            "Please install black code formater first! See the following link: https://black.readthedocs.io/en/stable/installation_and_usage.html"
        )

    # Get existing items
    existing_id_list = getattr(ctx.agent_config, "{}s".format(item_type))
    existing_item_list = [public_id.name for public_id in existing_id_list]

    item_type_plural = item_type + "s"

    # Load item specification yaml file
    try:
        config_loader = ConfigLoader("protocol-specification_schema.json",
                                     ProtocolSpecification)
        protocol_spec = config_loader.load_protocol_specification(
            open(specification_path))
    except Exception as e:
        raise click.ClickException(str(e))

    protocol_directory_path = os.path.join(ctx.cwd, item_type_plural,
                                           protocol_spec.name)

    # Check if we already have an item with the same name in the agent config
    logger.debug("{} already supported by the agent: {}".format(
        item_type_plural, existing_item_list))
    if protocol_spec.name in existing_item_list:
        raise click.ClickException(
            "A {} with name '{}' already exists. Aborting...".format(
                item_type, protocol_spec.name))
    # Check if we already have a directory with the same name in the resource directory (e.g. protocols) of the agent's directory
    if os.path.exists(protocol_directory_path):
        raise click.ClickException(
            "A directory with name '{}' already exists. Aborting...".format(
                protocol_spec.name))

    ctx.clean_paths.append(protocol_directory_path)
    try:
        agent_name = ctx.agent_config.agent_name
        click.echo(
            "Generating {} '{}' and adding it to the agent '{}'...".format(
                item_type, protocol_spec.name, agent_name))

        output_path = os.path.join(ctx.cwd, item_type_plural)
        protocol_generator = ProtocolGenerator(protocol_spec, output_path)
        protocol_generator.generate()

        # Add the item to the configurations
        logger.debug("Registering the {} into {}".format(
            item_type, DEFAULT_AEA_CONFIG_FILE))
        existing_id_list.add(
            PublicId("fetchai", protocol_spec.name, protocol_spec.version))
        ctx.agent_loader.dump(
            ctx.agent_config,
            open(os.path.join(ctx.cwd, DEFAULT_AEA_CONFIG_FILE), "w"))
    except FileExistsError:
        raise click.ClickException(
            "A {} with this name already exists. Please choose a different name and try again."
            .format(item_type))
    except ProtocolSpecificationParseError as e:
        raise click.ClickException(
            "The following error happened while parsing the protocol specification: "
            + str(e))
    except Exception as e:
        raise click.ClickException(
            "There was an error while generating the protocol. The protocol is NOT generated. Exception: "
            + str(e))

    # Run black code formatting
    try:
        subp = subprocess.Popen(  # nosec
            [
                sys.executable,
                "-m",
                "black",
                os.path.join(item_type_plural, protocol_spec.name),
                "--quiet",
            ])
        subp.wait(10.0)
    finally:
        poll = subp.poll()
        if poll is None:  # pragma: no cover
            subp.terminate()
            subp.wait(5)

    _fingerprint_item(click_context, "protocol", protocol_spec.public_id)