diff --git a/diagrams/__init__.py b/diagrams/__init__.py index f6d30d0b..9f9dcfc9 100644 --- a/diagrams/__init__.py +++ b/diagrams/__init__.py @@ -165,7 +165,7 @@ class Diagram: def connect(self, node: "Node", node2: "Node", edge: "Edge") -> None: """Connect the two Nodes.""" - self.dot.edge(node.hashid, node2.hashid, **edge.to_dot()) + self.dot.edge(node.hashid, node2.hashid, **edge.attrs()) def subgraph(self, dot: Digraph) -> None: """Create a subgraph for clustering""" @@ -403,7 +403,7 @@ class Edge: reverse: bool = False, label: str = "", color: str = "", - style: str = "" + style: str = "", ): """Edge represents an edge between two nodes. @@ -420,9 +420,9 @@ class Edge: self.node = node self.forward = forward self.reverse = reverse - self.label = label - self.color = color - self.style = style + + # graphviz complains about using label for edges, so replacing it with xlabel + self._attrs = {"xlabel": label, "color": color, "style": style} def __sub__(self, other: Union["Node", "Edge", List["Node"]]): """Implement Self - Node or Edge and Self - [Nodes]""" @@ -454,15 +454,12 @@ class Edge: result = [] for o in other: if isinstance(o, Edge): - o.color = self.color - o.label = self.label - o.style = self.style o.forward = forward if forward is not None else o.forward o.reverse = forward if forward is not None else o.reverse + self._attrs = o._attrs.copy() result.append(o) else: - result.append(Edge(o, forward=forward, reverse=reverse, - color=self.color, label=self.label, style=self.style)) + result.append(Edge(o, forward=forward, reverse=reverse, **self._attrs)) return result def connect(self, other: Union["Node", "Edge", List["Node"]]): @@ -471,9 +468,7 @@ class Edge: self.node.connect(node, self) return other elif isinstance(other, Edge): - self.label = other.label - self.color = other.color - self.style = other.style + self._attrs = other._attrs.copy() return self else: if self.node is not None: @@ -482,23 +477,17 @@ class Edge: self.node = other return self - def to_dot(self) -> Dict: - dot = {} + def attrs(self) -> Dict: if self.forward and self.reverse: - dot['dir'] = 'both' + direction = 'both' elif self.forward: - dot['dir'] = 'forward' + direction = 'forward' elif self.reverse: - dot['dir'] = 'back' + direction = 'back' else: - dot['dir'] = 'none' - if self.label: - dot['label'] = self.label - if self.color: - dot['color'] = self.color - if self.style: - dot['style'] = self.style - return dot + direction = 'none' + + return {**self._attrs, 'dir': direction} Group = Cluster diff --git a/docs/getting-started/examples.md b/docs/getting-started/examples.md index bae6512b..5b450f2e 100644 --- a/docs/getting-started/examples.md +++ b/docs/getting-started/examples.md @@ -213,6 +213,49 @@ with Diagram("Advanced Web Service with On-Premise", show=False): ![advanced web service with on-premise diagram](/img/advanced_web_service_with_on-premise.png) +## Advanced Web Service with On-Premise (with colors and labels) + +```python +from diagrams import Cluster, Diagram, Edge +from diagrams.onprem.analytics import Spark +from diagrams.onprem.compute import Server +from diagrams.onprem.database import PostgreSQL +from diagrams.onprem.inmemory import Redis +from diagrams.onprem.logging import Fluentd +from diagrams.onprem.monitoring import Grafana, Prometheus +from diagrams.onprem.network import Nginx +from diagrams.onprem.queue import Kafka + +with Diagram(name="Advanced Web Service with On-Premise (colored)", show=False): + ingress = Nginx("ingress") + + metrics = Prometheus("metric") + metrics << Edge(color="firebrick", style="dashed") << Grafana("monitoring") + + with Cluster("Service Cluster"): + grpcsvc = [ + Server("grpc1"), + Server("grpc2"), + Server("grpc3")] + + with Cluster("Sessions HA"): + master = Redis("session") + master - Edge(color="brown", style="dashed") - Redis("replica") << Edge(label="collect") << metrics + grpcsvc >> Edge(color="brown") >> master + + with Cluster("Database HA"): + master = PostgreSQL("users") + master - Edge(color="brown", style="dotted") - PostgreSQL("slave") << Edge(label="collect") << metrics + grpcsvc >> Edge(color="black") >> master + + aggregator = Fluentd("logging") + aggregator >> Edge(label="parse") >> Kafka("stream") >> Edge(color="black", style="bold") >> Spark("analytics") + + ingress >> Edge(color="darkgreen") << grpcsvc >> Edge(color="darkorange") >> aggregator +``` + +![advanced web service with on-premise diagram](/img/advanced_web_service_with_on-premise_colored.png) + ## RabbitMQ Consumers with Custom Nodes ```python @@ -242,27 +285,4 @@ with Diagram("Broker Consumers", show=False): queue >> consumers >> Aurora("Database") ``` -![rabbitmq consumers diagram](/img/rabbitmq_consumers_diagram.png) - -## Diagram with Custom Edges - -```python -from diagrams import Edge -from diagrams.aws.compute import EC2 - -# line -[EC2("node3"), EC2("node4")] - Edge(color='red', label='label1', style='dotted') - EC2("node") - -# list of nodes, one directional -[EC2("node3"), EC2("node4")] >> Edge(color='red', label='label1', style='dotted') >> EC2("node") -[EC2("node3"), EC2("node4")] << Edge(color='green', label='label2', style='dashed') << EC2("node") - -# both directional -EC2("node") << Edge(color='blue', label='label3', style='bold') >> EC2("node") - -# loop -node = EC2("node") -node >> Edge(color='pink', label='label4', style='solid') << node -``` - -![custom edges diagram](/img/custom_edges_diagram.png) +![rabbitmq consumers diagram](/img/rabbitmq_consumers_diagram.png) \ No newline at end of file diff --git a/website/static/img/advanced_web_service_with_on-premise_colored.png b/website/static/img/advanced_web_service_with_on-premise_colored.png new file mode 100644 index 00000000..f775cd50 Binary files /dev/null and b/website/static/img/advanced_web_service_with_on-premise_colored.png differ diff --git a/website/static/img/custom_edges_diagram.png b/website/static/img/custom_edges_diagram.png deleted file mode 100644 index 69ae35cc..00000000 Binary files a/website/static/img/custom_edges_diagram.png and /dev/null differ