diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index b53f4f6..7dbdcb8 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -11,7 +11,7 @@ "plugins": [ { "category": "deployment", - "description": "Deploy applications to AWS with architecture recommendations, cost estimates, and IaC deployment.", + "description": "Deploy applications to AWS with architecture recommendations, cost estimates, IaC deployment, and architecture diagram generation.", "keywords": [ "aws", "aws agent skills", @@ -20,12 +20,14 @@ "cdk", "cloudformation", "infrastructure", - "pricing" + "pricing", + "diagram", + "architecture" ], "name": "deploy-on-aws", "source": "./plugins/deploy-on-aws", - "tags": ["aws", "deploy", "infrastructure", "cdk"], - "version": "1.1.0" + "tags": ["aws", "deploy", "infrastructure", "cdk", "diagram"], + "version": "1.2.0" }, { "category": "location", diff --git a/README.md b/README.md index 8a3dbfb..941572a 100644 --- a/README.md +++ b/README.md @@ -82,6 +82,7 @@ Equips agents with the skills to accelerate AWS deployment - recommending AWS ar | Agent Skill | Triggers | | ----------- | --------------------------------------------------------------------------------------------------------------------- | | **deploy** | "deploy to AWS", "host on AWS", "run this on AWS", "AWS architecture", "estimate AWS cost", "generate infrastructure" | +| **diagram** | "architecture diagram", "draw architecture", "generate diagram", "infrastructure diagram", "AWS diagram" | ### MCP Servers diff --git a/plugins/deploy-on-aws/.claude-plugin/plugin.json b/plugins/deploy-on-aws/.claude-plugin/plugin.json index 9c74d83..28e5a9d 100644 --- a/plugins/deploy-on-aws/.claude-plugin/plugin.json +++ b/plugins/deploy-on-aws/.claude-plugin/plugin.json @@ -2,7 +2,7 @@ "author": { "name": "Amazon Web Services" }, - "description": "Deploy applications to AWS with architecture recommendations, cost estimates, and IaC deployment.", + "description": "Deploy applications to AWS with architecture recommendations, cost estimates, IaC deployment, and architecture diagram generation.", "homepage": "https://github.com/awslabs/agent-plugins", "keywords": [ "aws", @@ -10,10 +10,12 @@ "infrastructure", "cdk", "cloudformation", - "pricing" + "pricing", + "diagram", + "architecture" ], "license": "Apache-2.0", "name": "deploy-on-aws", "repository": "https://github.com/awslabs/agent-plugins", - "version": "1.1.0" + "version": "1.2.0" } diff --git a/plugins/deploy-on-aws/skills/diagram/SKILL.md b/plugins/deploy-on-aws/skills/diagram/SKILL.md new file mode 100644 index 0000000..85660e7 --- /dev/null +++ b/plugins/deploy-on-aws/skills/diagram/SKILL.md @@ -0,0 +1,80 @@ +--- +name: diagram +description: "Generate architecture diagrams as code using the Python diagrams DSL. Triggers on phrases like: architecture diagram, system design diagram, draw architecture, generate diagram, infrastructure diagram, AWS diagram, Kubernetes diagram, network diagram, visualize architecture." +--- + +# Architecture Diagram Generation + +Generate architecture diagrams using the Python [diagrams](https://diagrams.mingrammer.com/) package. Write a Python script, run it, and produce a PNG. + +Supports AWS (29 service categories), Kubernetes, on-premises, GCP, SaaS, and custom icons via the `diagrams` DSL. + +## When to Load Reference Files + +Load the appropriate reference file based on what the user is building: + +- **Any diagram** -> ALWAYS load [references/dsl-syntax.md](references/dsl-syntax.md) first for DSL syntax, constructor options, connections, clusters, and edge styles +- **AWS architecture**, **cloud infrastructure**, or **AWS services** -> load [references/aws-services.md](references/aws-services.md) for AWS import paths, common icons, and 5 AWS examples +- **Kubernetes**, **on-premises**, **SaaS**, **flowcharts**, **sequence diagrams**, **custom icons**, or **non-AWS diagrams** -> load [references/non-aws-providers.md](references/non-aws-providers.md) for K8s, on-prem, flowchart, and custom icon examples + +## Workflow + +1. Load [references/dsl-syntax.md](references/dsl-syntax.md) +2. Load the relevant provider reference (AWS or non-AWS) +3. Write a Python script using the `diagrams` DSL +4. Run: `mkdir -p generated-diagrams && python diagram.py` +5. Verify the PNG was created in `generated-diagrams/` + +## Critical Rules + +- ALWAYS set `show=False` in `Diagram()` constructor +- ALWAYS set `filename="generated-diagrams/"` (no `.png` extension) +- ALWAYS use explicit imports: `from diagrams.aws.compute import EC2` +- ALWAYS run `mkdir -p generated-diagrams` before executing +- Use `Cluster()` to group related resources (VPCs, subnets, namespaces) +- Use `Edge(label=, color=, style=)` for labeled or styled connections + +## Defaults + +Default output format: PNG +Default layout direction: TB (top-to-bottom) + +Override syntax: + +- "left to right" -> Use `direction="LR"` +- "SVG format" -> Use `outformat="svg"` + +When not specified, ALWAYS use `direction="TB"` and `outformat="png"`. + +## Prerequisites + +Requires two dependencies installed locally: + +1. **GraphViz** (system package providing `dot`): + - macOS: `brew install graphviz` + - Ubuntu/Debian: `sudo apt-get install graphviz` + - Amazon Linux/RHEL: `sudo yum install graphviz` +2. **Python diagrams package**: `pip install diagrams` + +**Verify:** `dot -V && python3 -c "import diagrams; print('OK')"` + +### Missing Dependencies + +If `dot` command not found: + +- Inform user: "GraphViz is not installed. Required for diagram rendering." +- Show install command for detected OS +- DO NOT attempt to generate diagrams without GraphViz + +If `import diagrams` fails: + +- Inform user: "Python diagrams package not installed." +- Show: `pip install diagrams` +- DO NOT proceed without the package + +## References + +- [DSL syntax and patterns](references/dsl-syntax.md) +- [AWS services and examples](references/aws-services.md) +- [Non-AWS providers and examples](references/non-aws-providers.md) +- [diagrams documentation](https://diagrams.mingrammer.com/) diff --git a/plugins/deploy-on-aws/skills/diagram/references/aws-services.md b/plugins/deploy-on-aws/skills/diagram/references/aws-services.md new file mode 100644 index 0000000..8f15918 --- /dev/null +++ b/plugins/deploy-on-aws/skills/diagram/references/aws-services.md @@ -0,0 +1,111 @@ +# AWS Services and Examples + +## AWS Service Categories + +| Category | Import Path | Common Icons | +|----------|------------|--------------| +| `analytics` | `diagrams.aws.analytics` | Athena, EMR, Glue, Kinesis, Redshift, Quicksight | +| `compute` | `diagrams.aws.compute` | EC2, Lambda, ECS, EKS, Fargate, Batch | +| `database` | `diagrams.aws.database` | RDS, Aurora, DynamoDB, ElastiCache, Redshift, Neptune | +| `integration` | `diagrams.aws.integration` | SQS, SNS, StepFunctions, EventBridge, MQ | +| `management` | `diagrams.aws.management` | CloudWatch, CloudFormation, SystemsManager | +| `ml` | `diagrams.aws.ml` | Sagemaker, Rekognition, Comprehend, Bedrock | +| `network` | `diagrams.aws.network` | VPC, ELB, ALB, NLB, CloudFront, Route53, APIGateway | +| `security` | `diagrams.aws.security` | IAM, Cognito, WAF, KMS, Shield, SecretsManager | +| `storage` | `diagrams.aws.storage` | S3, EBS, EFS, FSx, Backup | +| `general` | `diagrams.aws.general` | User, Users, Client, InternetGateway | + +Other categories: `ar`, `blockchain`, `business`, `cost`, `devtools`, `enablement`, `enduser`, `engagement`, `game`, `iot`, `media`, `migration`, `mobile`, `quantum`, `robotics`, `satellite`. + +## Example: Basic Web Service + +```python +from diagrams import Diagram +from diagrams.aws.compute import EC2 +from diagrams.aws.database import RDS +from diagrams.aws.network import ELB + +with Diagram("Web Service", show=False, filename="generated-diagrams/aws-basic"): + ELB("lb") >> EC2("web") >> RDS("userdb") +``` + +## Example: Grouped Workers + +```python +from diagrams import Diagram +from diagrams.aws.compute import EC2 +from diagrams.aws.database import RDS +from diagrams.aws.network import ELB + +with Diagram("Grouped Workers", show=False, direction="TB", filename="generated-diagrams/aws-workers"): + ELB("lb") >> [EC2("w1"), EC2("w2"), EC2("w3"), EC2("w4"), EC2("w5")] >> RDS("events") +``` + +## Example: Clustered Web Services + +```python +from diagrams import Diagram, Cluster +from diagrams.aws.compute import ECS +from diagrams.aws.database import RDS, ElastiCache +from diagrams.aws.network import ELB, Route53 + +with Diagram("Clustered Web Services", show=False, filename="generated-diagrams/aws-clustered"): + dns = Route53("dns") + lb = ELB("lb") + with Cluster("Services"): + svc_group = [ECS("web1"), ECS("web2"), ECS("web3")] + with Cluster("DB Cluster"): + db_primary = RDS("userdb") + db_primary - [RDS("userdb ro")] + memcached = ElastiCache("memcached") + dns >> lb >> svc_group + svc_group >> db_primary + svc_group >> memcached +``` + +## Example: Event Processing + +```python +from diagrams import Diagram, Cluster +from diagrams.aws.compute import ECS, EKS, Lambda +from diagrams.aws.analytics import Redshift +from diagrams.aws.integration import SQS +from diagrams.aws.storage import S3 + +with Diagram("Event Processing", show=False, filename="generated-diagrams/aws-events"): + source = EKS("k8s source") + with Cluster("Event Flows"): + with Cluster("Event Workers"): + workers = [ECS("w1"), ECS("w2"), ECS("w3")] + queue = SQS("event queue") + with Cluster("Processing"): + handlers = [Lambda("p1"), Lambda("p2"), Lambda("p3")] + store = S3("events store") + dw = Redshift("analytics") + source >> workers >> queue >> handlers + handlers >> store + handlers >> dw +``` + +## Example: S3 Image Processing with Bedrock + +```python +from diagrams import Diagram, Cluster, Edge +from diagrams.aws.compute import Lambda +from diagrams.aws.general import User +from diagrams.aws.ml import Bedrock +from diagrams.aws.storage import S3 + +with Diagram("S3 Image Processing", show=False, direction="LR", filename="generated-diagrams/aws-bedrock"): + user = User("User") + with Cluster("S3 Bucket"): + input_folder = S3("Input") + output_folder = S3("Output") + fn = Lambda("Processor") + bedrock = Bedrock("Claude Sonnet") + user >> Edge(label="Upload") >> input_folder + input_folder >> Edge(label="Trigger") >> fn + fn >> Edge(label="Process") >> bedrock + bedrock >> Edge(label="Result") >> fn + fn >> Edge(label="Save") >> output_folder +``` diff --git a/plugins/deploy-on-aws/skills/diagram/references/dsl-syntax.md b/plugins/deploy-on-aws/skills/diagram/references/dsl-syntax.md new file mode 100644 index 0000000..3e3823b --- /dev/null +++ b/plugins/deploy-on-aws/skills/diagram/references/dsl-syntax.md @@ -0,0 +1,110 @@ +# Diagrams DSL Syntax Reference + +## Basic Structure + +```python +from diagrams import Diagram, Cluster, Edge +from diagrams.aws.compute import EC2, Lambda +from diagrams.aws.database import RDS +from diagrams.aws.network import ELB + +with Diagram("Title", show=False, filename="generated-diagrams/name"): + with Cluster("VPC"): + lb = ELB("ALB") + with Cluster("Private Subnet"): + servers = [EC2("web1"), EC2("web2")] + db = RDS("PostgreSQL") + lb >> servers >> db +``` + +## Diagram Constructor + +```python +Diagram( + name="Diagram Title", # Title shown on the diagram + show=False, # ALWAYS False -- don't open viewer + filename="path/name", # Output path (no .png extension) + direction="TB", # TB (top-bottom), LR (left-right), BT, RL + outformat="png", # png (default), jpg, svg, pdf +) +``` + +## Connections + +```python +node1 >> node2 >> node3 # Left to right flow +node1 << node2 # Right to left flow +node1 - node2 # Bidirectional +node1 >> [node2, node3, node4] # Fan out to multiple +node1 >> Edge(label="HTTPS", color="darkgreen", style="dashed") >> node2 +``` + +## Clusters + +```python +with Cluster("VPC"): + with Cluster("Public Subnet"): + lb = ELB("ALB") + with Cluster("Private Subnet"): + app = [EC2("app1"), EC2("app2")] + with Cluster("Data"): + db = RDS("db") + lb >> app >> db +``` + +## Edge Styles + +| Parameter | Values | +|-----------|--------| +| `color` | `"darkgreen"`, `"firebrick"`, `"brown"`, `"darkorange"`, `"black"`, any CSS color | +| `style` | `"solid"`, `"dashed"`, `"dotted"`, `"bold"` | +| `label` | Any string | + +## Provider Import Paths + +| Provider | Import Pattern | Example | +|----------|---------------|---------| +| AWS | `diagrams.aws.` | `from diagrams.aws.compute import EC2` | +| GCP | `diagrams.gcp.` | `from diagrams.gcp.storage import GCS` | +| Kubernetes | `diagrams.k8s.` | `from diagrams.k8s.compute import Pod` | +| On-premises | `diagrams.onprem.` | `from diagrams.onprem.database import PostgreSQL` | +| SaaS | `diagrams.saas.` | `from diagrams.saas.chat import Slack` | +| Programming | `diagrams.programming.` | `from diagrams.programming.flowchart import Action` | +| Generic | `diagrams.generic.` | `from diagrams.generic.compute import Rack` | +| Custom | `diagrams.custom` | `Custom("name", "icon.png")` | + +## Common Patterns + +### Fan-out / Fan-in + +```python +source >> [worker1, worker2, worker3] >> sink +``` + +### Bidirectional with Replica + +```python +primary = RDS("primary") +primary - RDS("replica") +``` + +### Nested Clusters + +```python +with Cluster("VPC"): + with Cluster("Public"): + lb = ELB("ALB") + with Cluster("Private"): + app = [EC2("app1"), EC2("app2")] + lb >> app +``` + +### Custom Nodes + +```python +from diagrams.custom import Custom +from urllib.request import urlretrieve + +icon_path, _ = urlretrieve("https://example.com/icon.png", "icon.png") +custom_node = Custom("My Service", icon_path) +``` diff --git a/plugins/deploy-on-aws/skills/diagram/references/non-aws-providers.md b/plugins/deploy-on-aws/skills/diagram/references/non-aws-providers.md new file mode 100644 index 0000000..b4b040f --- /dev/null +++ b/plugins/deploy-on-aws/skills/diagram/references/non-aws-providers.md @@ -0,0 +1,122 @@ +# Non-AWS Providers and Examples + +## Kubernetes Categories + +| Category | Common Icons | +|----------|-------------| +| `k8s.compute` | Pod, Deployment, StatefulSet, ReplicaSet, DaemonSet, Job | +| `k8s.network` | Service, Ingress, NetworkPolicy | +| `k8s.storage` | PV, PVC, StorageClass | +| `k8s.controlplane` | APIServer, Scheduler, ControllerManager | +| `k8s.clusterconfig` | HPA, Namespace, Quota | +| `k8s.rbac` | Role, RoleBinding, ClusterRole | + +## On-Premises Categories + +| Category | Common Icons | +|----------|-------------| +| `onprem.compute` | Server | +| `onprem.database` | PostgreSQL, MySQL, MongoDB, Cassandra | +| `onprem.container` | Docker | +| `onprem.ci` | Jenkins, GitlabCI, GithubActions | +| `onprem.monitoring` | Prometheus, Grafana, Datadog | +| `onprem.logging` | Fluentd, Loki | +| `onprem.queue` | Kafka, RabbitMQ, Celery | +| `onprem.network` | Nginx, HAProxy, Traefik | +| `onprem.inmemory` | Redis, Memcached | +| `onprem.vcs` | Git, Github, Gitlab | +| `onprem.iac` | Terraform, Ansible | + +## Flowchart Shapes + +```python +from diagrams.programming.flowchart import ( + Action, # Rectangle -- process step + Decision, # Diamond -- yes/no branch + InputOutput, # Parallelogram -- data input/output + Predefined, # Double-border rectangle -- predefined process + Delay, # Half-oval -- wait/delay +) +``` + +## Example: Kubernetes Exposed Pod + +```python +from diagrams import Diagram +from diagrams.k8s.compute import Deployment, Pod, ReplicaSet +from diagrams.k8s.clusterconfig import HPA +from diagrams.k8s.network import Ingress, Service + +with Diagram("Exposed Pod", show=False, filename="generated-diagrams/k8s-exposed"): + net = Ingress("domain.com") >> Service("svc") + net >> [Pod("pod1"), Pod("pod2"), Pod("pod3")] << ReplicaSet("rs") << Deployment("dp") << HPA("hpa") +``` + +## Example: Order Processing Flow + +```python +from diagrams import Diagram +from diagrams.programming.flowchart import Action, Decision, Delay, InputOutput, Predefined + +with Diagram("Order Processing", show=False, filename="generated-diagrams/flow"): + start = Predefined("Start") + order = InputOutput("Order Received") + check = Decision("In Stock?") + process = Action("Process Order") + wait = Delay("Backorder") + ship = Action("Ship Order") + end = Predefined("End") + start >> order >> check + check >> process >> ship >> end + check >> wait >> process +``` + +## Example: On-Premises with Colored Edges + +```python +from diagrams import Diagram, Cluster, Edge +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("On-Prem Service", show=False, filename="generated-diagrams/onprem"): + 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"): + primary = Redis("session") + primary - Edge(color="brown", style="dashed") - Redis("replica") + grpcsvc >> Edge(color="brown") >> primary + with Cluster("Database HA"): + db = PostgreSQL("users") + db - Edge(color="brown", style="dotted") - PostgreSQL("replica") + grpcsvc >> Edge(color="black") >> db + aggregator = Fluentd("logging") + aggregator >> Edge(label="parse") >> Kafka("stream") + ingress >> Edge(color="darkgreen") << grpcsvc >> Edge(color="darkorange") >> aggregator +``` + +## Example: Custom Icons + +```python +from diagrams import Diagram, Cluster +from diagrams.aws.database import Aurora +from diagrams.custom import Custom +from diagrams.k8s.compute import Pod +from urllib.request import urlretrieve + +rabbitmq_url = "https://jpadilla.github.io/rabbitmqapp/assets/img/icon.png" +rabbitmq_icon, _ = urlretrieve(rabbitmq_url, "rabbitmq.png") + +with Diagram("Custom Icons", show=False, filename="generated-diagrams/custom"): + with Cluster("Consumers"): + consumers = [Pod("worker"), Pod("worker"), Pod("worker")] + queue = Custom("Message queue", rabbitmq_icon) + queue >> consumers >> Aurora("Database") +```