Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue sweeping - Terraform 0.12.2, Windows, Docker & PLY #65

Merged
merged 4 commits into from
Jun 25, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
96 changes: 49 additions & 47 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -1,50 +1,52 @@
version: 2
version: 2.1
aliases:
- &setup_remote_docker
setup_remote_docker:
version: 18.09.3
docker_layer_caching: true
- &docker_login
run: echo "$DOCKER_PASSWORD" | docker login -u "$DOCKER_LOGIN" --password-stdin
executors:
buildpack:
environment:
IMAGE_NAME: $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME
TF_VERSION: 0.12.2
docker:
- image: circleci/buildpack-deps
jobs:
build:
working_directory: /build
docker:
- image: docker:17.05.0-ce-git
executor: buildpack
steps:
- checkout
- *setup_remote_docker
- *docker_login
- run: docker build --build-arg TF_VERSION=$TF_VERSION -t $IMAGE_NAME .
- run: docker save -o image.tar $IMAGE_NAME
- persist_to_workspace:
root: .
paths:
- ./image.tar
release:
executor: buildpack
steps:
- checkout
- setup_remote_docker
- run:
name: Install dependencies
command: |
apk add --no-cache \
py-pip=9.0.0-r1
pip install \
docker-compose==1.12.0
- restore_cache:
keys:
- v1-{{ .Branch }}
paths:
- /caches/app.tar
- run:
name: Load Docker image layer cache
command: |
set +o pipefail
docker load -i /caches/app.tar | true
- run:
name: Build application Docker image
command: |
docker build --cache-from=app -t 28mm/blast-radius .
- run:
name: Save Docker image layer cache
command: |
mkdir -p /caches
docker save -o /caches/app.tar 28mm/blast-radius
- save_cache:
key: v1-{{ .Branch }}-{{ epoch }}
paths:
- /caches/app.tar
- run:
name: Run tests
command: |
true
- deploy:
name: Push application Docker image
command: |
if [ "${CIRCLE_BRANCH}" == "master" ]; then
docker login -u $DOCKER_LOGIN -p $DOCKER_PASSWORD
docker push 28mm/blast-radius
fi
- attach_workspace:
at: /tmp/workspace
- *setup_remote_docker
- *docker_login
- run: docker load -i /tmp/workspace/image.tar
- run: docker tag $IMAGE_NAME $IMAGE_NAME:$TF_VERSION
- run: |-
docker push $IMAGE_NAME:latest
docker push $IMAGE_NAME:$TF_VERSION

workflows:
version: 2
builder:
jobs:
- build
- release:
requires:
- build
filters:
branches:
only: master
4 changes: 4 additions & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
.*
doc
providers/
LICENSE
58 changes: 13 additions & 45 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,53 +1,21 @@
#Dockerfile to encapsulate both terraform and blast-radius
#
#How-to build docker image (from working-directory having blast-radius source)
# docker build -t blast-radius .
#
#How-to run docker container (from working-directory having *.tf files)
# By default, the --serve arg is passed internally to blast-radius
#
# Syntax to run in foreground (to stop: ^C):
# docker run -it --rm -p 5000:5000 -v $(pwd):/workdir blast-radius
#
# Syntax to run detached (to stop: docker rm -f blast1):
# docker run -d --name blast1 -p 5000:5000 -v $(pwd):/workdir blast-radius
ARG TF_VERSION=0.12.2
ARG PYTHON_VERSION=3.7

#Implementation notes
# Using ubuntu (rather than alpine) base image due to problems with graphviz fonts on alpine
FROM hashicorp/terraform:$TF_VERSION AS terraform

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

#define default terraform version in environment var
ENV TF_VERSION "0.12.0"
COPY --from=terraform /bin/terraform /bin/terraform
COPY ./docker-entrypoint.sh /bin/docker-entrypoint.sh
RUN chmod +x /bin/docker-entrypoint.sh

#expose blast-radius port
EXPOSE 5000

#install graphviz and py dependencies
RUN apt-get update \
&& apt-get install -y \
curl \
git \
graphviz \
python3 \
python3-pip \
jq \
unzip \
&& rm -rf /var/lib/apt/lists/*

#install terraform
WORKDIR /src
COPY . .
RUN chmod +x ./docker-build.sh \
&& ./docker-build.sh /src

#create blast-radius package from source
RUN pip3 install -e .
RUN pip install -e .

#set up entrypoint script
RUN chmod +x ./docker-entrypoint.sh
WORKDIR /data

#set up runtime workdir for tf files
WORKDIR /workdir
ENTRYPOINT ["/src/docker-entrypoint.sh"]
CMD ["--serve"]
ENTRYPOINT ["/bin/docker-entrypoint.sh"]
CMD ["blast-radius", "--serve"]
168 changes: 117 additions & 51 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,85 +1,151 @@
# Blast Radius

[![PyPI version](https://badge.fury.io/py/BlastRadius.svg)](https://badge.fury.io/py/BlastRadius) ![CircleCI](https://img.shields.io/circleci/project/github/28mm/blast-radius.svg)
[![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)

*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 cloud providers, through [example configurations](https://28mm.github.io/blast-radius-docs/).
* **Document** your infrastructure
* **Reason** about relationships between resources, and evaluate changes to them.
[terraform]: https://www.terraform.io/
[examples]: https://28mm.github.io/blast-radius-docs/

<img src="doc/blastradius-interactive.png">
_Blast Radius_ is a tool for reasoning about [Terraform][] dependency graphs
with interactive visualizations.

* **Interact** with this diagram (and many others) [here](https://28mm.github.io/blast-radius-docs/).
Use _Blast Radius_ to:

# Quickstart
* __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]

Install *Blast Radius* with pip, and *Graphviz* through your system's package manager.
![screenshot](doc/blastradius-interactive.png)

````bash
[...]$ pip3 install BlastRadius
[...]$ brew install graphviz
````
## Prerequisites

Point *Blast Radius* at an `init-ed` *Terraform* project, and connect with your browser.
* [Graphviz](https://www.graphviz.org/)
* [Python](https://www.python.org/) 3.7 or newer

```bash
[...]$ blast-radius --serve /path/to/terraform-project
* Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
> __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/.

## Docker
*Alternatively*, you can launch *Blast Radius* in a docker container. (In this example, the current working directory contains a *Terraform* project.)

```bash
[...]$ docker run --security-opt apparmor:unconfined --cap-add=SYS_ADMIN -it --rm -p 5000:5000 -v $(pwd):/workdir:ro 28mm/blast-radius
[privileges]: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities
[overlayfs]: https://wiki.archlinux.org/index.php/Overlay_filesystem

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
```

*Please note*: because terraform saves module links as _absolute_ paths in _.terraform/modules/<uuid>_ we mount the host's filesystem read-only and force terraform to update the modules path at start. This way we don't interfere with the real project. Thus docker has to be run with the `--cap-add=SYS_ADMIN` flag to use the [overlayFS](https://wiki.archlinux.org/index.php/Overlay_filesystem) see [Docker's documentation](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities).
A slightly more customized variant of this is also available as an example
[docker-compose.yml](./examples/docker-compose.yml) usecase for Workspaces.

### 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.

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
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
our the [runtime privileges][privileges] documentation.

*Additional note*:
If you organised your terraform directories with stacks and modules, please call *Blast Radius* from the root directory and give the stack's directory as argument (plus the `--serve` argument).
#### Docker & Subdirectories

```bash
[...]$ tree -d
/-- project
|-- modules
If you organized your *Terraform* project using stacks and modules,
*Blast Radius* must be called from the project root and reference them as
subdirectories -- don't forget to prefix `--serve`!

For example, let's create a Terraform `project` with the following:

```txt
$ tree -d
`-- project/
|-- modules/
| |-- foo
| |-- bar
| `-- dead
`-- stacks
`-- beef
`-- stacks/
`-- beef/
`-- .terraform
```

[...]$ cd project
docker run --cap-add=SYS_ADMIN -it --rm -p 5000:5000 -v $(pwd):/workdir:ro 28mm/blast-radius --serve stacks/beef
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
```
# Embedded Figures

You may wish to embed figures produced with *Blast Radius* in other documents. You will need the following:
## Embedded Figures

You may wish to embed figures produced with *Blast Radius* in other documents.
You will need the following:

1. an `svg` file and `json` document representing the graph and its layout.
2. `javascript` and `css` found in `.../blastradius/server/static`
3. a uniquely identified DOM element, where the `<svg>` should appear.
1. An `svg` file and `json` document representing the graph and its layout.
2. `javascript` and `css` found in `.../blastradius/server/static`
3. A uniquely identified DOM element, where the `<svg>` should appear.

Further details available [here](doc/embedded.md).
You can read more details in the [documentation](docs/embedeed.md)

# Implementation Details
## Implementation Details

*Blast Radius* uses the [*Graphviz*](http://graphviz.org/) package to layout graph diagrams, [*PyHCL*](https://github.com/virtuald/pyhcl) to parse [*Terraform*](https://www.terraform.io/) configurations, and [*d3.js*](https://d3js.org/) to implement interactive features and animations.
*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.

# Further Reading
## Further Reading

The development of *Blast Radius* is documented in a series of [blog](https://28mm.github.io) posts:
The development of *Blast Radius* is documented in a series of
[blog](https://28mm.github.io) posts:

* [part 1](https://28mm.github.io/notes/d3-terraform-graphs): motivations, d3 force-directed layouts vs. vanilla graphviz.
* [part 2](https://28mm.github.io/notes/d3-terraform-graphs-2): d3-enhanced graphviz layouts, meaningful coloration, animations.
* [part 3](https://28mm.github.io/notes/terraform-graphs-3): limiting horizontal sprawl, supporting modules.
* [part 4](https://28mm.github.io/notes/d3-terraform-graphs-4): search, pan/zoom, prune-to-selection, docker.
* [part 1](https://28mm.github.io/notes/d3-terraform-graphs): motivations, d3 force-directed layouts vs. vanilla graphviz.
* [part 2](https://28mm.github.io/notes/d3-terraform-graphs-2): d3-enhanced graphviz layouts, meaningful coloration, animations.
* [part 3](https://28mm.github.io/notes/terraform-graphs-3): limiting horizontal sprawl, supporting modules.
* [part 4](https://28mm.github.io/notes/d3-terraform-graphs-4): search, pan/zoom, prune-to-selection, docker.

A catalog of example *Terraform* configurations, and their dependency graphs can be found [here](https://28mm.github.io/blast-radius-docs/).
A catalog of example *Terraform* configurations, and their dependency graphs
can be found [here](https://28mm.github.io/blast-radius-docs/).

* [AWS two-tier architecture](https://28mm.github.io/blast-radius-docs/examples/terraform-provider-aws/two-tier/)
* [AWS networking (featuring modules)](https://28mm.github.io/blast-radius-docs/examples/terraform-provider-aws/networking/)
* [Google two-tier architecture](https://28mm.github.io/blast-radius-docs/examples/terraform-provider-google/two-tier/)
* [Azure load-balancing with 2 vms](https://28mm.github.io/blast-radius-docs/examples/terraform-provider-azurem/2-vms-loadbalancer-lbrules/)
* [AWS two-tier architecture](https://28mm.github.io/blast-radius-docs/examples/terraform-provider-aws/two-tier/)
* [AWS networking (featuring modules)](https://28mm.github.io/blast-radius-docs/examples/terraform-provider-aws/networking/)
* [Google two-tier architecture](https://28mm.github.io/blast-radius-docs/examples/terraform-provider-google/two-tier/)
* [Azure load-balancing with 2 vms](https://28mm.github.io/blast-radius-docs/examples/terraform-provider-azurem/2-vms-loadbalancer-lbrules/)

These examples are drawn primarily from the `examples/` directory distributed with various *Terraform* providers, and aren't necessarily ideal. Additional examples, particularly demonstrations of best-practices, or of multi-cloud configurations strongly desired.
These examples are drawn primarily from the `examples/` directory distributed
with various *Terraform* providers, and aren't necessarily ideal. Additional
examples, particularly demonstrations of best-practices, or of multi-cloud
configurations strongly desired.
Loading