Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
18e3e2c
modified blast-radius
nibhart1 Apr 24, 2020
7567708
npm packaging (#3)
Sep 4, 2020
f85b7d0
new version Blast radius 0.1.25.1 (#4)
nishubharti Sep 17, 2020
ce8e614
corrected title name
nbharti1 Sep 18, 2020
61a734b
Merge pull request #5 from nishubharti/fix-branch
nishubharti Sep 18, 2020
f6a490c
added version name
nbharti1 Sep 18, 2020
4646def
Merge pull request #6 from nishubharti/fix-b
nishubharti Sep 18, 2020
a61783d
removed hcl2json dependency
nbharti1 Sep 23, 2020
2f5ca6f
Merge pull request #7 from nishubharti/minor-release
nishubharti Sep 23, 2020
23fe4a7
added version name
nbharti1 Sep 23, 2020
e158203
Merge pull request #8 from nishubharti/test
nishubharti Sep 23, 2020
c8ba26b
modified version
nbharti1 Sep 23, 2020
d190295
Merge pull request #9 from nishubharti/tmp
nishubharti Sep 23, 2020
99d68f9
zoom reset feature (#10)
Oct 19, 2020
7752fe5
pan reset feature (#11)
Oct 19, 2020
09f9b4c
handle xml fetch error (#12)
Dec 4, 2020
4f0cadd
modified version
nbharti1 Sep 23, 2020
a8fdd07
added time estimation info
nbharti1 Dec 1, 2020
0cbc1bd
icon implemented in graph
nbharti1 Dec 22, 2020
68fb548
fix for selectize selection
Feb 19, 2021
489a39c
Merge pull request #13 from nishubharti/icon
nishubharti Feb 25, 2021
382c618
updated blast-radius version
nbharti1 Feb 25, 2021
2665e81
Merge pull request #14 from nishubharti/icon
nishubharti Feb 25, 2021
702f89c
added graphviz dependency in requirement.txt
nbharti1 Jul 26, 2021
fd31934
Merge pull request #15 from nishubharti/icon
nishubharti Jul 26, 2021
40c8abf
added graphviz in requirement.txt
nbharti1 Jul 26, 2021
84ab5ec
fixed issues
nbharti1 Jul 28, 2021
b055629
Merge pull request #16 from nishubharti/version
nishubharti Jul 28, 2021
116d9f1
policy decision based iamge icon fix
nbharti1 Jul 29, 2021
9ff3541
Merge pull request #17 from nishubharti/version
nishubharti Jul 29, 2021
18f12e4
fixed missing json2yaml
nbharti1 Aug 9, 2021
e825350
Merge pull request #18 from nishubharti/version
nishubharti Aug 9, 2021
42465dd
changes font size of the text
nbharti1 Aug 10, 2021
19dfac4
Merge pull request #19 from nishubharti/version
nishubharti Aug 10, 2021
9328872
modified readme
nbharti1 Aug 17, 2021
32cec8f
Merge pull request #20 from nishubharti/version
nishubharti Aug 17, 2021
34e3c05
minor fix
nbharti1 Sep 17, 2021
6d9f2d8
fixed controls failed structure
nbharti1 Oct 5, 2021
683ca3c
Merge pull request #21 from nishubharti/fix-zoom
nishubharti Oct 5, 2021
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,7 @@ venv.bak/

# mypy
.mypy_cache/

# node_modules
node_modules
package-lock.json
20 changes: 17 additions & 3 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,21 +1,35 @@
ARG TF_VERSION=0.12.12
ARG TF_VERSION=0.12.20
ARG PYTHON_VERSION=3.7

FROM python:$PYTHON_VERSION-alpine



FROM hashicorp/terraform:$TF_VERSION AS terraform
FROM ibmterraform/terraform-provider-ibm-docker AS provideribm
FROM nibhart1/hcl2json:hcl2json AS hcl2json

FROM python:$PYTHON_VERSION-alpine
RUN pip install -U pip ply \
&& apk add --update --no-cache graphviz ttf-freefont

RUN pip install graphviz
COPY --from=terraform /bin/terraform /bin/terraform
COPY --from=provideribm /go/bin/terraform-provider-ibm_v* /root/.terraform.d/plugins/linux_amd64/terraform-provider-ibm
COPY --from=hcl2json /go/bin/hcl2json /bin/hcl2json
COPY ./docker-entrypoint.sh /bin/docker-entrypoint.sh
RUN chmod +x /bin/docker-entrypoint.sh

WORKDIR /bin
RUN ls

WORKDIR /src
COPY . .
RUN pip install -e .

WORKDIR /data

ENTRYPOINT ["/bin/docker-entrypoint.sh"]
CMD ["blast-radius", "--serve"]




14 changes: 14 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,25 @@
CATEGORIES_JSON = ./blastradius/server/static/js/categories.json
CATEGORIES_JS = ./blastradius/server/static/js/categories.js

GOPATH = $(CURDIR)/blastradius
export GOPATH

.PHONY: clean
clean:
-find . -type d -name __pycache__ -exec rm -r {} \+
-rm $(CATEGORIES_JSON)
-rm $(CATEGORIES_JS)
-rm -rf hcl2json

# install
.PHONY: install
install: hcl2json
pipenv install

# build hcl2json binary
.PHONY: hcl2json
hcl2json:
-go get github.com/tmccombs/hcl2json

# build pypi package
.PHONY: dist
Expand Down
133 changes: 85 additions & 48 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,47 +1,89 @@
# Blast Radius

[![CircleCI](https://circleci.com/gh/28mm/blast-radius/tree/master.svg?style=svg)](https://circleci.com/gh/28mm/blast-radius/tree/master)
[![PyPI version](https://badge.fury.io/py/BlastRadius.svg)](https://badge.fury.io/py/BlastRadius)

[terraform]: https://www.terraform.io/
[examples]: https://28mm.github.io/blast-radius-docs/
[overlayfs]:

_Blast Radius_ is a tool for reasoning about [Terraform][] dependency graphs
with interactive visualizations.
_Blast Radius_ is a tool for reasoning about [Terraform][] dependency graphs with interactive visualizations.

Use _Blast Radius_ to:

* __Learn__ about *Terraform* or one of its providers through real [examples][]
* __Document__ your infrastructure
* __Reason__ about relationships between resources and evaluate changes to them
* __Interact__ with the diagram below (and many others) [in the docs][examples]
* __Interact__ with the diagrams below (and many others) [in the docs][examples]

![screenshot](doc/blastradius-interactive.png)
---

## Blast Radius
![screenshot](doc/blastradiusext.png)

---

## Prerequisites

* [Graphviz](https://www.graphviz.org/)
> __Note:__ For macOS you can `brew install graphviz`
* [Python](https://www.python.org/) 3.7 or newer
* [Go](https://golang.org/) 1.12.16 or newer
* [Terraform][] 0.12.x or newer

> __Note:__ For macOS you can `brew install graphviz`
---

## Quickstart

The fastest way to get up and running with *Blast Radius* is to install it with
`pip` to your pre-existing environment:

```sh
pip install blastradius
```

Once installed just point *Blast Radius* at any initialized *Terraform*
directory:

```sh
blast-radius --serve /path/to/terraform/directory
```

And you will shortly be rewarded with a browser link http://127.0.0.1:5000/.
For fastest way to get up and running with blast-radius is as follows:

* Download and install the wheel files from the [release](https://github.com/nishubharti/blast-radius/releases)

```
copy the blastradius/server/static folder to the terraform directory
```
```
easy_install blastradius-0.1.25.4-py3-none-any.whl
```
or
```
pip3 blastradius-0.1.25.4-py3-none-any.whl
```

* Once installed just point Blast Radius at any initialized Terraform directory:
```sh
blast-radius --serve /path/to/terraform/directory
```
* Go to the browser link http://127.0.0.1:5000/ to view the Blast Radius diagram for the terraform file.

![BlastRadius](doc/blastradiusext.png)

* Enrich the Blast Radius diagrams with the outcome of Terraform plan & apply actions:
```
terraform plan --out tfplan.binary
terraform show -json tfplan.binary > tfplan.json
terraform apply
```
for including cost and policy information into blast-radius cost.json and policy.json file need to be stored into the working directory.

```sh
blast-radius --serve /path/to/terraform/directory
```
* Go to the browser link http://127.0.0.1:5000/ to view the Blast Radius extended diagram

The enrichments include - information from the Plan file, State file , cost file and time file .
Click the columns adjacent to the Resource Names to view these enrichment in the side panel view.

![BlastRadiusExt](doc/blast-radius-ext.png)

---

## Build your own wheel file

* Create wheel file of this repo
```sh
python3 setup.py sdist bdist_wheel
```
---

## Docker

Expand All @@ -50,34 +92,28 @@ And you will shortly be rewarded with a browser link http://127.0.0.1:5000/.

To launch *Blast Radius* for a local directory by manually running:

```sh
docker run --rm -it -p 5000:5000 \
-v $(pwd):/data:ro \
--security-opt apparmor:unconfined \
--cap-add=SYS_ADMIN \
28mm/blast-radius
```
* create a dockerhub account
```sh
docker build -t <dockerhub_username>/blast-radius:v1 .
docker push <dockerhub_username>/blast-radius:v1
```

A slightly more customized variant of this is also available as an example
[docker-compose.yml](./examples/docker-compose.yml) usecase for Workspaces.
```sh
docker run --cap-add=SYS_ADMIN -dit -p 5000:5000 -v <path>:/data:ro <dockerhub_username>/blast-radius:v1
```

### Docker configurations

*Terraform* module links are saved as _absolute_ paths in relative to the
project root (note `.terraform/modules/<uuid>`). Given these paths will vary
betwen Docker and the host, we mount the volume as read-only, assuring we don't
ever interfere with your real environment.
betwen Docker and the host, we mount the volume as read-only, assuring we don't ever interfere with your real environment.

However, in order for *Blast Radius* to actually work with *Terraform*, it needs
to be initialized. To accomplish this, the container creates an [overlayfs][]
that exists within the container, overlaying your own, so that it can operate
However, in order for *Blast Radius* to actually work with *Terraform*, it needs to be initialized as well as planned compulsory. To accomplish this, the container creates an [overlayfs][] that exists within the container, overlaying your own, so that it can operate
independently. To do this, certain runtime privileges are required --
specifically `--cap-add=SYS_ADMIN`.

For more information on how this works and what it means for your host, check
out the [runtime privileges][privileges] documentation.

#### Docker & Subdirectories
### Docker & Subdirectories

If you organized your *Terraform* project using stacks and modules,
*Blast Radius* must be called from the project root and reference them as
Expand All @@ -101,14 +137,12 @@ It consists of 3 modules `foo`, `bar` and `dead`, followed by one `beef` stack.
To apply *Blast Radius* to the `beef` stack, you would want to run the container
with the following:

```sh
$ cd project
$ docker run --rm -it -p 5000:5000 \
-v $(pwd):/data:ro \
--security-opt apparmor:unconfined \
--cap-add=SYS_ADMIN \
28mm/blast-radius --serve stacks/beef
```
```sh
$ cd project
$ docker run --cap-add=SYS_ADMIN -dit -p 5000:5000 -v <pathofdirectory>:/data:ro <dockerhub_username>/blast-radius:v1
```

---

## Embedded Figures

Expand All @@ -121,11 +155,14 @@ You will need the following:

You can read more details in the [documentation](doc/embedded.md)

---

## Implementation Details

*Blast Radius* uses the [Graphviz][] package to layout graph diagrams,
[PyHCL](https://github.com/virtuald/pyhcl) to parse [Terraform][] configuration,
and [d3.js](https://d3js.org/) to implement interactive features and animations.
[hcl] to parse [Terraform][] configuration, and [d3.js](https://d3js.org/) to implement interactive features and animations.

---

## Further Reading

Expand Down
40 changes: 26 additions & 14 deletions bin/blast-radius
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,22 @@ import sys
import argparse
import os
import itertools
import subprocess

# 1st party libraries
from blastradius.handlers.dot import DotGraph, Format, DotNode
from blastradius.handlers.plan import Plan
from blastradius.handlers.apply import Apply
from blastradius.handlers.terraform import Terraform
from blastradius.server.server import app
from blastradius.handlers.cost import Cost
from blastradius.handlers.policy import Policy
from blastradius.handlers.time import Time

# from blastradius.server.server import simple_graph, run_tf_graph
from blastradius.server.server import simple_graph



def main():

Expand All @@ -27,33 +36,32 @@ def main():
output_group.add_argument('--json', action='store_const', const=True, default=False, help='print a json representation of the Terraform graph')
output_group.add_argument('--dot', action='store_const', const=True, default=False, help='print the graphviz/dot representation of the Terraform graph')
output_group.add_argument('--svg', action='store_const', const=True, default=False, help='print the svg representation of the Terraform graph')
output_group.add_argument('--svg-ext', action='store_const', const=True, default=False, help='download the simple svg of modified svg representation of the Terraform graph')
output_group.add_argument('--serve', action='store_const', const=True, default=False, help='spins up a webserver with an interactive Terraform graph')

parser.add_argument('--graph', type=str, help='`terraform graph` output (defaults to stdin)', default=sys.stdin)

# options to limit, re-focus, and re-center presentation of larger graphs.
constraint_group = parser.add_mutually_exclusive_group()
constraint_group.add_argument('--module-depth', type=int, help='hide module details', required=False)
constraint_group.add_argument('--focus', type=str, help='', required=False)
constraint_group.add_argument('--center', type=str, help='', required=False)

# TODO present changes, and animate `terraform apply'
#parser.add_argument('--plan', type=str, help='terraform plan output', default=None)
#parser.add_argument('--state', type=str, help='tfstate file', default=None)
#parser.add_argument('--apply', type=str, help='terraform apply log', default=None)

args = parser.parse_args()

if args.serve:
os.chdir(args.directory)
app.run(host='0.0.0.0',port=args.port)
sys.exit(0)

elif args.json or args.dot or args.svg:
elif args.json or args.dot or args.svg or args.svg_ext:
if args.graph is sys.stdin:
dot = DotGraph('', file_contents=sys.stdin.read())
dot = DotGraph('','', file_contents=sys.stdin.read())
elif args.svg_ext:
#for simple blasradius svg
dot = DotGraph('ext','',file_contents=simple_graph())
else:
dot = DotGraph(args.graph)
dot = DotGraph('','',file_contents=simple_graph())

# we might not want to show every node in the depedency graph
# specifying --module-depth is an easy way to limit detail
Expand All @@ -76,21 +84,25 @@ def main():
parser.print_help()
sys.exit(1)
dot.focus(f_node)

if args.json:
tf = Terraform(args.directory)
for node in dot.nodes:
node.definition = tf.get_def(node)

if args.json:
print(dot.json())
f = open("visualization.json", "a")
f.write(dot.json())
f.close()
elif args.dot:
print(dot.dot())
elif args.svg:
print(dot.svg())
elif args.svg_ext:
f = open("visualization.svg", "a")
f.write(dot.svg())
f.close()
else:
parser.print_help()


if __name__ == '__main__':
main()
main()
Loading