Exemple #1
0
async def fetch_blueprint_from_github_url(opp: OpenPeerPower,
                                          url: str) -> ImportedBlueprint:
    """Get a blueprint from a github url."""
    import_url = _get_github_import_url(url)
    session = aiohttp_client.async_get_clientsession(opp)

    resp = await session.get(import_url, raise_for_status=True)
    raw_yaml = await resp.text()
    data = yaml.parse_yaml(raw_yaml)
    blueprint = Blueprint(data)

    parsed_import_url = yarl.URL(import_url)
    suggested_filename = f"{parsed_import_url.parts[1]}/{parsed_import_url.parts[-1]}"
    if suggested_filename.endswith(".yaml"):
        suggested_filename = suggested_filename[:-5]

    return ImportedBlueprint(suggested_filename, raw_yaml, blueprint)
Exemple #2
0
def _extract_blueprint_from_community_topic(
    url: str,
    topic: dict,
) -> ImportedBlueprint | None:
    """Extract a blueprint from a community post JSON.

    Async friendly.
    """
    block_content = None
    blueprint = None
    post = topic["post_stream"]["posts"][0]

    for match in COMMUNITY_CODE_BLOCK.finditer(post["cooked"]):
        block_syntax, block_content = match.groups()

        if block_syntax not in ("auto", "yaml"):
            continue

        block_content = html.unescape(block_content.strip())

        try:
            data = yaml.parse_yaml(block_content)
        except OpenPeerPowerError:
            if block_syntax == "yaml":
                raise

            continue

        if not is_blueprint_config(data):
            continue

        blueprint = Blueprint(data)
        break

    if blueprint is None:
        raise OpenPeerPowerError(
            "No valid blueprint found in the topic. Blueprint syntax blocks need to be marked as YAML or no syntax."
        )

    return ImportedBlueprint(f'{post["username"]}/{topic["slug"]}',
                             block_content, blueprint)
Exemple #3
0
async def fetch_blueprint_from_github_gist_url(opp: OpenPeerPower,
                                               url: str) -> ImportedBlueprint:
    """Get a blueprint from a Github Gist."""
    if not url.startswith("https://gist.github.com/"):
        raise UnsupportedUrl("Not a GitHub gist url")

    parsed_url = yarl.URL(url)
    session = aiohttp_client.async_get_clientsession(opp)

    resp = await session.get(
        f"https://api.github.com/gists/{parsed_url.parts[2]}",
        headers={"Accept": "application/vnd.github.v3+json"},
        raise_for_status=True,
    )
    gist = await resp.json()

    blueprint = None
    filename = None
    content = None

    for filename, info in gist["files"].items():
        if not filename.endswith(".yaml"):
            continue

        content = info["content"]
        data = yaml.parse_yaml(content)

        if not is_blueprint_config(data):
            continue

        blueprint = Blueprint(data)
        break

    if blueprint is None:
        raise OpenPeerPowerError(
            "No valid blueprint found in the gist. The blueprint file needs to end with '.yaml'"
        )

    return ImportedBlueprint(f"{gist['owner']['login']}/{filename[:-5]}",
                             content, blueprint)
Exemple #4
0
async def ws_save_blueprint(opp, connection, msg):
    """Save a blueprint."""

    path = msg["path"]
    domain = msg["domain"]

    domain_blueprints: dict[str,
                            models.DomainBlueprints] | None = opp.data.get(
                                DOMAIN, {})

    if domain not in domain_blueprints:
        connection.send_error(msg["id"], websocket_api.ERR_INVALID_FORMAT,
                              "Unsupported domain")

    try:
        blueprint = models.Blueprint(yaml.parse_yaml(msg["yaml"]),
                                     expected_domain=domain)
        if "source_url" in msg:
            blueprint.update_metadata(source_url=msg["source_url"])
    except OpenPeerPowerError as err:
        connection.send_error(msg["id"], websocket_api.ERR_INVALID_FORMAT,
                              str(err))
        return

    try:
        await domain_blueprints[domain].async_add_blueprint(blueprint, path)
    except FileAlreadyExists:
        connection.send_error(msg["id"], "already_exists",
                              "File already exists")
        return
    except OSError as err:
        connection.send_error(msg["id"], websocket_api.ERR_UNKNOWN_ERROR,
                              str(err))
        return

    connection.send_result(msg["id"], )
Exemple #5
0
def test_input():
    """Test loading inputs."""
    data = {"hello": yaml.Input("test_name")}
    assert yaml.parse_yaml(yaml.dump(data)) == data