Skip to content
This repository has been archived by the owner on Dec 9, 2024. It is now read-only.

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
lucasepe committed Jun 5, 2020
0 parents commit 2adfc66
Show file tree
Hide file tree
Showing 58 changed files with 1,554 additions and 0 deletions.
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
## Intellij
.idea/**/workspace.xml
.idea/**/tasks.xml
.idea/**/encodings.xml
.idea/**/compiler.xml
.idea/**/misc.xml
.idea/**/modules.xml
.idea/**/vcs.xml

## VSCode
.vscode/

## File-based project format:
*.iws
*.iml
.idea/

# Binaries for programs and plugins
*.exe
*.exe~
*.dll
*.so
*.dylib
*.dat
*.DS_Store
go.sum

# Test binary, built with `go test -c`
*.test

# Output of the go coverage tool, specifically when used with LiteIDE
*.out

# Goreleaser builds
dist/**

21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2020 Luca Sepe

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
261 changes: 261 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,261 @@
# Draft

A commandline tool that generate **H**igh **L**evel microservice & serverless **A**rchitecture diagrams using a declarative syntax defined in a YAML file.

- Works on Linux, Mac OSX, Windows
- Just a single portable binary file
- It Does One Thing Well
- Input data in flat YAML text files
- Usable with shell scripts
- Can take input from pipes `cat`

## How `draft` works?

`draft` takes in input a declarative YAML file and generates a [`dot`](https://en.wikipedia.org/wiki/DOT_(graph_description_language)) script for [Graphviz](https://www.graphviz.org/)

```bash
draft backend-for-frontend.yml | dot -Tpng -Gdpi=200 > backend-for-frontend.png
```

Piping the `draft` output to [GraphViz](http://www.graphviz.org/doc/info/output.html/) `dot` you can generate the following output formats:

| format | command |
|:-------------|:---------------------------------------------------------------|
| GIF | <code>draft input.yml &#124; dot -Tgif > output.gif</code> |
| JPEG | <code>draft input.yml &#124; dot -Tjpg > output.jpg</code> |
| PostScript | <code>draft input.yml &#124; dot -Tps > output.ps</code> |
| PSD | <code>draft input.yml &#124; dot -Tpsd > output.psd</code> |
| SVG | <code>draft input.yml &#124; dot -Tsvg > output.svg</code> |
| WebP | <code>draft input.yml &#124; dot -Twebp > output.webp</code> |

To install GraphViz to your favorite OS, please, follow this link [https://graphviz.gitlab.io/download/](https://graphviz.gitlab.io/download/).

## Components

### A picture is worth a thousand words

... and this is particularly true in regard to complex IT architectures.

The basic unit of each _draft_ design is the `component`:

```go
type Component struct {
ID string `yaml:"id,omitempty"` // optional - autogenerated if omitted (read more for details...)
Kind string `yaml:"kind"` // required (one of: service, gateway, queue, broker, function, storage, database)
Label string `yaml:"label,omitempty"` // optional - the component description (or scope)
Provider string `yaml:"provider,omitempty"` // optional - you can use this to specify the implementation
FillColor string `yaml:"fillColor,omitempty"` // optional - the hex code for the background color
FontColor string `yaml:"fontColor,omitempty"` // optional - the hex code for the foreground color
Rounded bool `yaml:"rounded,omitempty"` // optional - set to true if you wants rounded shapes
}
```

Draft uses a set of symbols independent from the different providers (AWS, Microsoft Azure, GCP).

- you can eventually describe the implementation using the `provider` attribute.

Below is a list of all the components currently implemented.

| Component | Kind | YAML | Output |
|:-------------------|:------------|:--------------------------|:--------------------------------:|
| **Client** | `client` | ![](./examples/cl.jpg) | ![](./examples/client.png) |
| **Microservice** | `service` | ![](./examples/ms.jpg) | ![](./examples/service.png) |
| **Gateway** | `gateway` | ![](./examples/gt.jpg) | ![](./examples/gateway.png) |
| **Message Broker** | `broker` | ![](./examples/br.jpg) | ![](./examples/broker.png) |
| **Queue Service** | `queue` | ![](./examples/qs.jpg) | ![](./examples/queue.png) |
| **Object Storage** | `storage` | ![](./examples/st.jpg) | ![](./examples/storage.png) |
| **Function** | `function` | ![](./examples/fn.jpg) | ![](./examples/function.png) |
| **Database** | `database` | ![](./examples/db.jpg) | ![](./examples/database.png) |

## Connections

You can connect each component by arrows.

To be able to connect an _origin component_ with one or more _target component_ you need to specify each `componentId`.

- you can define your component `id` explicitly
- you can omit the component `id` attribute and it will be autogenerated

### Autogenerated `id`

An autogenerated `id` has a prefix and a sequential number

- the prefix is related to the component `kind`

Aautogenerated `id` prefix mapping.

| a kind of... | will generate an `id` prefix with... | examples |
|:-------------|:-------------------------------------|:---------------|
| `client` | `cl` | `cl1, cl2,...` |
| `service` | `ms` | `ms1, ms2,...` |
| `gateway` | `gt` | `gt1, gt2,...` |
| `broker` | `br` | `br1, br2,...` |
| `queue` | `qs` | `qs1, qs2,...` |
| `storage` | `st` | `st1, st2,...` |
| `function` | `fn` | `fn1, fn2,...` |
| `database` | `db` | `db1, db2,...` |

A `connection` has the following properties:

```go
type Connection struct {
Origin struct {
ComponentID string `yaml:"componentId"`
} `yaml:"origin"`
Targets []struct {
ComponentID string `yaml:"componentId"`
Label string `yaml:"label,omitempty"`
Color string `yaml:"color,omitempty"`
Dashed bool `yaml:"dashed,omitempty"`
Dir string `yaml:"dir,omitempty"`
Highlight bool `yaml:"highlight,omitempty"`
} `yaml:"targets"`
}
```

## Example 1 - Message Bus Pattern

Create the `draft` architecture descriptor YAML with your favorite editor:

```yaml
title: message bus pattern
backgroundColor: '#ffffff'
components:
-
kind: service
label: Producer
provider: AWS EC2
-
kind: broker
label: "Notification\nService"
provider: AWS SNS
-
kind: queue
label: "event queue @ topic 1"
provider: AWS SQS
-
kind: queue
label: "event queue @ topic 2"
provider: AWS SQS
-
kind: service
label: "Consumer\n@ topic 1"
provider: AWS EC2
-
kind: service
label: "Consumer\n@ topic 2"
provider: AWS EC2
connections:
-
origin:
componentId: ms1
targets:
-
componentId: br1
-
origin:
componentId: br1
targets:
-
componentId: qs1
dashed: true
-
componentId: qs2
dashed: true
-
origin:
componentId: qs1
targets:
-
componentId: ms2
dir: back
-
origin:
componentId: qs2
targets:
-
componentId: ms3
dir: back
```
Then run `draft`:

```bash
draft message-bus-pattern.yml | dot -Tpng > message-bus-pattern.png
```

Here the generated output:

![](./examples/message-bus-pattern.png)


## Example 2 - AWS Cognito Custom Authentication Flow

Create the draft architecture descriptor YAML with your favorite editor:

```yaml
title: Amazon Cognito Custom Authentication Flow with external database
backgroundColor: '#ffffff'
components:
-
kind: client
label: "Web App"
-
kind: client
label: "Mobile App"
-
kind: service
label: "Cognito"
provider: "AWS Cognito"
fillColor: '#991919'
fontColor: '#fafafa'
-
kind: function
label: "Define\nAuthChallange"
provider: "AWS Lambda"
-
kind: function
label: "Create\nAuthChallange"
provider: "AWS Lambda"
-
kind: function
label: "Verify\nAuthChallange"
provider: "AWS Lambda"
-
kind: database
label: "Users\nRepository"
provider: "AWS RDS"
connections:
-
origin:
componentId: cl1
targets:
-
componentId: ms1
-
origin:
componentId: cl2
targets:
-
componentId: ms1
-
origin:
componentId: ms1
targets:
-
componentId: fn1
-
componentId: fn2
-
componentId: fn3
-
origin:
componentId: fn2
targets:
-
componentId: db1
```

Here the generated output:

![](./examples/aws-cognito-custom-auth-flow.png)
54 changes: 54 additions & 0 deletions broker.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
package draft

import (
"fmt"
"strings"

"github.com/emicklei/dot"
"github.com/lucasepe/draft/pkg/cluster"
"github.com/lucasepe/draft/pkg/node"
)

type broker struct {
seq int16
}

func (rcv *broker) nextID() string {
rcv.seq++
return fmt.Sprintf("br%d", rcv.seq)
}

func (rcv *broker) sketch(graph *dot.Graph, comp Component) {
id := comp.ID
if strings.TrimSpace(comp.ID) == "" {
id = rcv.nextID()
}

label := comp.Label
if strings.TrimSpace(comp.Label) == "" {
label = "Message Broker"
}

cl := cluster.New(graph, id, cluster.Label(comp.Provider))

el := node.New(cl, id,
node.Label(label),
node.Rounded(comp.Rounded),
node.FontColor(comp.FontColor),
node.FillColor(comp.FillColor, "#e0eeeeff"),
node.Shape("cds"),
)
el.Attr("height", "0.8")
}

/** Alternative
label=<table border="0" cellspacing="0">
<tr><td border="1" align="center"><font point-size="8"><b>&nbsp;topic 1&nbsp;</b></font></td></tr>
<tr><td border="1" align="center"><font point-size="8"><b>&nbsp;topic 2&nbsp;</b></font></td></tr>
<tr><td border="1" align="center"><font point-size="8"><b>&nbsp;...&nbsp;</b></font></td></tr>
<tr><td border="1" align="center"><font point-size="8"><b>&nbsp;topic N&nbsp;</b></font></td></tr>
</table> >
shape="plain"
**/
Loading

0 comments on commit 2adfc66

Please sign in to comment.