diff --git a/diagrams/__init__.py b/diagrams/__init__.py
index a9e0f0c..57c9213 100644
--- a/diagrams/__init__.py
+++ b/diagrams/__init__.py
@@ -36,6 +36,10 @@ def getcluster():
def setcluster(cluster):
__cluster.set(cluster)
+def new_init(cls, init):
+ def reset_init(*args, **kwargs):
+ cls.__init__ = init
+ return reset_init
class Diagram:
__directions = ("TB", "BT", "LR", "RL")
@@ -211,8 +215,13 @@ class Cluster:
# Cluster direction does not work now. Graphviz couldn't render
# correctly for a subgraph that has a different rank direction.
def __init__(
- self, label: str = "cluster", direction: str = "LR", graph_attr: dict = {},
- ):
+ self,
+ label: str = "cluster",
+ direction: str = "LR",
+ graph_attr: dict = {},
+ icon: object = None,
+ icon_size: int = 30
+ ):
"""Cluster represents a cluster context.
:param label: Cluster label.
@@ -221,13 +230,24 @@ class Cluster:
"""
self.label = label
self.name = "cluster_" + self.label
+ self.icon = icon
+ self.icon_size = icon_size
self.dot = Digraph(self.name)
# Set attributes.
for k, v in self._default_graph_attrs.items():
self.dot.graph_attr[k] = v
- self.dot.graph_attr["label"] = self.label
+
+ # if an icon is set, try to find and instantiate a Node without calling __init__()
+ # then find it's icon by calling _load_icon()
+ if self.icon:
+ _node = self.icon(_no_init=True)
+ if isinstance(_node,Node):
+ self.icon_label = '<
| ' + self.label + ' |
>'
+ self.dot.graph_attr["label"] = self.icon_label
+ else:
+ self.dot.graph_attr["label"] = self.label
if not self._validate_direction(direction):
raise ValueError(f'"{direction}" is not a valid direction')
@@ -284,6 +304,14 @@ class Node:
_height = 1.9
+ def __new__(cls, *args, **kwargs):
+ instance = object.__new__(cls)
+ lazy = kwargs.pop('_no_init', False)
+ if not lazy:
+ return instance
+ cls.__init__ = new_init(cls, cls.__init__)
+ return instance
+
def __init__(self, label: str = "", **attrs: Dict):
"""Node represents a system component.
diff --git a/docs/guides/cluster.md b/docs/guides/cluster.md
index 6cbf820..5001597 100644
--- a/docs/guides/cluster.md
+++ b/docs/guides/cluster.md
@@ -66,6 +66,29 @@ with Diagram("Event Processing", show=False):
handlers >> dw
```
+## Clusters with icons in the label
+
+You can add a Node icon before the cluster label (and specify its size as well). You need to import the used Node class first.
+
+```python
+from diagrams import Cluster, Diagram
+from diagrams.aws.compute import ECS
+from diagrams.aws.database import RDS, Aurora
+from diagrams.aws.network import Route53, VPC
+
+with Diagram("Simple Web Service with DB Cluster", show=False):
+ dns = Route53("dns")
+ web = ECS("service")
+
+ with Cluster(label='VPC',icon=VPC):
+ with Cluster("DB Cluster",icon=Aurora,icon_size=30):
+ db_master = RDS("master")
+ db_master - [RDS("slave1"),
+ RDS("slave2")]
+
+ dns >> web >> db_master
+```
+
![event processing diagram](/img/event_processing_diagram.png)
-> There is no depth limit of nesting. Feel free to create nested clusters as deep as you want.
\ No newline at end of file
+> There is no depth limit of nesting. Feel free to create nested clusters as deep as you want.