dhall-awsdac

May 30, 2026 · View on GitHub

A Dhall library for awsdac (awslabs/diagram-as-code). Describe AWS architecture diagrams in type-safe Dhall, convert to awsdac-compatible YAML with dhall-to-yaml, then render to PNG with the awsdac CLI.

diagram.dhall ──dhall-to-yaml──► diagram.yaml ──awsdac──► diagram.png

Requirements

ToolPurposeNotes
dhallType-checking and hashingbrew install dhall
dhall-to-yaml or dhall-to-yaml-ngYAML conversionbrew install dhall-yaml (provides dhall-to-yaml-ng)
awsdacRender YAML to PNGsubmodule HEAD is recommendedTitleFillColor, SpanResources, etc. landed after the 0.23 release

Build awsdac from the vendored submodule:

cd diagram-as-code && go build -o /usr/local/bin/awsdac ./cmd/awsdac

Quick start

-- diagram.dhall
let awsdac = ./package.dhall

let D     = awsdac.Defaults
let AWS   = awsdac.AWS.Types
let P     = awsdac.AWS.Presets
let Dir   = awsdac.Direction
let DF    = awsdac.DefinitionFile
let entry = awsdac.Schema.entry

in    D.Diagram
    ::  { Diagram =
          { DefinitionFiles = [ DF.awsLightIcons ]
          , Resources =
            [ entry "Canvas" D.Resource::{
              , Type = AWS.Diagram.Canvas
              , Direction = Dir.Vertical
              , Children = [ "VPC" ]
              }
            , entry "VPC" D.Resource::{
              , Type = AWS.EC2.VPC
              , Preset = P.AWSCloudNoLogo
              }
            ]
          , Links = [] : List awsdac.Schema.Link
          }
        }
dhall-to-yaml --omit-empty --file diagram.dhall > diagram.yaml
awsdac diagram.yaml -o diagram.png

Full examples: examples/alb-ec2.dhall, examples/vpc-natgw.dhall, examples/cloudfront-ecs-rds.dhall (CloudFront / S3 / ALB / ECS / RDS / ElastiCache with locally-composed helpers).


URL import

Pin via SHA256:

let awsdac =
      https://raw.githubusercontent.com/<owner>/dhall-awsdac/<tag>/package.dhall
        sha256:<hash>

The SHA256 for each tagged release is published on the Releases page (also attached as package.dhall.sha256). To recompute locally:

dhall hash --file package.dhall

Expect breaking changes during the v0.x series.


Layout

DirectoryContents
schema/Dhall types in 1:1 correspondence with the awsdac YAML schema
defaults/Default records for the :: operator — write only the required fields
types/Text constants for Position / Direction / Align / etc.
helpers/Color.rgba builders, DefinitionFile variant constructors, Arrow presets
aws/AWS::* type constants generated from the upstream awsdac icon definitions (~145 resource-level + ~184 service-level), plus preset names
examples/Sample diagrams
test/Round-trip tests
package.dhallPublic API entry point

API surface

let awsdac = ./package.dhall

awsdac.Schema.{Diagram, Resource, Link, ..., entry}  -- types + `entry` resource-map helper
awsdac.Defaults.{Diagram, Resource, Link, Label}     -- :: defaults
awsdac.{Position, Direction, Align, HeaderAlign, BorderType, LineStyle, LinkType, ArrowHeadType, IconFillType}
awsdac.Color.{rgba, rgb, rgbaClamped, rgbClamped, clamp255, transparent, black, white}
awsdac.DefinitionFile.{url, localFile, embed, awsLightIcons}  -- embed takes a Schema.Embed (DefinitionStructure)
awsdac.Arrow.{open, default}
awsdac.Layout.{hstack, vstack}  -- HorizontalStack / VerticalStack from a List Text of child names
awsdac.Link.{link, arrow}       -- link s sp t tp (no arrowhead); arrow s sp t tp (Arrow.open on target)
awsdac.AWS.Types.{Diagram, EC2, ElasticLoadBalancingV2, AutoScaling, RDS, Lambda, S3, IAM, DynamoDB, SQS, SNS, CloudFront, Route53, ApiGatewayV2, CloudWatch, ECS, ...}  -- ~145 resources; see aws/Types.dhall
awsdac.AWS.Services.{S3, EC2, CloudFront, Region, ...}  -- ~184 service-level icons; see aws/Services.dhall
awsdac.AWS.Presets.{AWSCloudNoLogo, PublicSubnet, PrivateSubnet, ApplicationLoadBalancer, NetworkLoadBalancer, User, BlankGroup, Empty}

Tests

Verifies that each Dhall example produces a byte-identical PNG to the upstream YAML sample:

bash test/render.sh
# Override the awsdac binary with $AWSDAC (defaults to the one on $PATH)
AWSDAC=/tmp/awsdac-head bash test/render.sh

test/render.sh performs:

  1. dhall type --file package.dhall (schema type-check)
  2. dhall hash --file package.dhall (prints the pinned SHA256)
  3. For each example: render dhall → yaml → png and upstream yaml → png, compare with cmp

limitations

  • AWS type constants are mechanically generated from the upstream awsdac icon-definition YAML (~145 resource-level entries in aws/Types.dhall, ~184 service-level entries in aws/Services.dhall). Anything upstream doesn't define can be written as a literal "AWS::Foo::Bar" string; awsdac falls back to the service-level icon when a resource type isn't recognised. Re-run python3 tools/gen-aws-types.py to refresh from upstream.
  • DefinitionFile.Embed is hand-translated from awsdac's definition.Definition Go struct. Drift from upstream must be tracked manually (no CI check yet).
  • No high-level abstractions like "create a VPC with public/private subnets" — users compose their own helpers.
  • Color.rgba / rgb cannot enforce the 0–255 range at the Dhall type level (documented as a contract). Use Color.rgbaClamped / rgbClamped for runtime-saturating variants when constructing colors from arithmetic.
  • Semantic awsdac constraints (e.g. Canvas must exist) are not expressible in Dhall and surface as awsdac runtime errors.
  • dhall-to-yaml emits record fields in alphabetical order, so Type is not at the top of each resource. Functionally harmless, just less readable.

License

Apache License 2.0. See LICENSE.