コード例 #1
0
ファイル: util_test.py プロジェクト: mesosphere/cloudkeeper
def test_value_in_path() -> None:
    js = {"foo": {"bla": {"test": 123}}}
    assert value_in_path(js, ["foo", "bla", "test"]) == 123
    assert value_in_path_get(
        js, ["foo", "bla", "test"],
        "foo") == "foo"  # expected string got int -> default value
    assert value_in_path(js, ["foo", "bla", "test", "bar"]) is None
    assert value_in_path_get(js, ["foo", "bla", "test", "bar"], 123) == 123
    assert value_in_path(js, ["foo", "bla", "bar"]) is None
    assert value_in_path_get(js, ["foo", "bla", "bar"], "foo") == "foo"
コード例 #2
0
 def count_successors_by(node_id: str, edge_type: str,
                         path: List[str]) -> Dict[str, int]:
     result: Dict[str, int] = {}
     to_visit = list(self.successors(node_id, edge_type))
     while to_visit:
         visit_next: List[str] = []
         for elem_id in to_visit:
             if elem_id not in visited:
                 visited.add(elem_id)
                 elem = self.nodes[elem_id]
                 if not value_in_path_get(elem, NodePath.is_phantom,
                                          False):
                     extracted = value_in_path(elem, path)
                     if isinstance(extracted, str):
                         result[extracted] = result.get(extracted,
                                                        0) + 1
                 # check if there is already a successor summary: stop the traversal and take the result.
                 existing = value_in_path(elem,
                                          NodePath.descendant_summary)
                 if existing and isinstance(existing, dict):
                     for summary_item, count in existing.items():
                         result[summary_item] = result.get(
                             summary_item, 0) + count
                 else:
                     visit_next.extend(
                         a for a in self.successors(elem_id, edge_type)
                         if a not in visited)
         to_visit = visit_next
     return result
コード例 #3
0
 def no_nested_props(js: Json) -> Json:
     reported: Json = value_in_path_get(js, NodePath.reported, {})
     res = {
         k: v
         for k, v in reported.items()
         if v is not None and not isinstance(v, (dict, list))
     }
     return res
コード例 #4
0
async def respond_cytoscape(
        gen: AsyncIterator[JsonElement]) -> AsyncGenerator[str, None]:
    # Note: this is a very inefficient way of creating a response, since it creates the graph in memory
    # on the server side, so we can reuse the networkx code.
    # This functionality can be reimplemented is a streaming way.
    graph = await result_to_graph(
        gen, lambda js: value_in_path_get(js, NodePath.reported, {}))
    yield json.dumps(cytoscape_data(graph))
コード例 #5
0
ファイル: render_dot.py プロジェクト: mesosphere/cloudkeeper
def render_dot(gen: Iterator[JsonElement]) -> Generator[str, None, None]:
    # We use the paired12 color scheme: https://graphviz.org/doc/info/colors.html with color names as 1-12
    cit = count_iterator()
    icon_map = generate_icon_map()
    colors: Dict[str, int] = defaultdict(lambda: (next(cit) % 12) + 1)
    node = "node [shape=plain colorscheme=paired12]"
    edge = "edge [arrowsize=0.5]"
    yield render_dot_header(node, edge)
    in_account: Dict[str, List[str]] = defaultdict(list)
    for item in gen:
        if isinstance(item, dict):
            type_name = item.get("type")
            if type_name == "node":
                uid = value_in_path(item, NodePath.node_id)
                if uid:
                    name = value_in_path_get(item, NodePath.reported_name,
                                             "n/a")
                    kind = value_in_path_get(item, NodePath.reported_kind,
                                             "n/a")
                    account = value_in_path_get(item,
                                                NodePath.ancestor_account_name,
                                                "graph_root")
                    id = value_in_path_get(item, NodePath.reported_id, "n/a")
                    parsed_kind = parse_kind(kind)
                    paired12 = kind_colors.get(parsed_kind, colors[kind])
                    in_account[account].append(uid)
                    resource = ResourceDescription(uid, name, id, parsed_kind,
                                                   kind)
                    yield render_resource(resource, icon_map, paired12)
            elif type_name == "edge":
                from_node = value_in_path(item, NodePath.from_node)
                to_node = value_in_path(item, NodePath.to_node)
                if from_node and to_node:
                    yield f' "{from_node}" -> "{to_node}" '
        else:
            raise AttributeError(
                f"Expect json object but got: {type(item)}: {item}")
    # All elements in the same account are rendered as dedicated subgraph
    for account, uids in in_account.items():
        yield f' subgraph "{account}" {{'
        for uid in uids:
            yield f'    "{uid}"'
        yield " }"

    yield "}"
コード例 #6
0
async def respond_dot(
        gen: AsyncIterator[JsonElement]) -> AsyncGenerator[str, None]:
    # We use the paired12 color scheme: https://graphviz.org/doc/info/colors.html with color names as 1-12
    cit = count_iterator()
    colors: Dict[str, int] = defaultdict(lambda: (next(cit) % 12) + 1)
    node = "node [shape=Mrecord colorscheme=paired12]"
    edge = "edge [arrowsize=0.5]"
    yield f"digraph {{\nrankdir=LR\noverlap=false\nsplines=true\n{node}\n{edge}"
    in_account: Dict[str, List[str]] = defaultdict(list)
    async for item in gen:
        if isinstance(item, dict):
            type_name = item.get("type")
            if type_name == "node":
                uid = value_in_path(item, NodePath.node_id)
                if uid:
                    name = re.sub(
                        "[^a-zA-Z0-9]", "",
                        value_in_path_get(item, NodePath.reported_name, "n/a"))
                    kind = value_in_path_get(item, NodePath.reported_kind,
                                             "n/a")
                    account = value_in_path_get(item,
                                                NodePath.ancestor_account_name,
                                                "graph_root")
                    paired12 = colors[kind]
                    in_account[account].append(uid)
                    yield f' "{uid}" [label="{name}|{kind}", style=filled fillcolor={paired12}];'
            elif type_name == "edge":
                from_node = value_in_path(item, NodePath.from_node)
                to_node = value_in_path(item, NodePath.to_node)
                edge_type = value_in_path(item, NodePath.edge_type)
                if from_node and to_node:
                    yield f' "{from_node}" -> "{to_node}" [label="{edge_type}"]'
        else:
            raise AttributeError(
                f"Expect json object but got: {type(item)}: {item}")
    # All elements in the same account are rendered as dedicated subgraph
    for account, uids in in_account.items():
        yield f' subgraph "{account}" {{'
        for uid in uids:
            yield f'    "{uid}"'
        yield " }"

    yield "}"
コード例 #7
0
 def resolved_kind(node: Json) -> Optional[str]:
     kinds: List[str] = value_in_path_get(node, NodePath.kinds, [])
     for kind in kinds:
         if kind in GraphResolver.resolved_ancestors:
             return kind
     return None