diff --git a/.circleci/config.yml b/.circleci/config.yml deleted file mode 100644 index d0b5457..0000000 --- a/.circleci/config.yml +++ /dev/null @@ -1,51 +0,0 @@ -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.12 - docker: - - image: circleci/buildpack-deps -jobs: - build: - executor: buildpack - steps: - - checkout - - *setup_remote_docker - - run: docker build --build-arg TF_VERSION=$TF_VERSION -t $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME . - - run: docker save -o image.tar $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME - - persist_to_workspace: - root: . - paths: - - ./image.tar - release: - executor: buildpack - steps: - - attach_workspace: - at: /tmp/workspace - - *setup_remote_docker - - *docker_login - - run: docker load -i /tmp/workspace/image.tar - - run: docker tag $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:$TF_VERSION - - run: |- - docker push $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:latest - docker push $CIRCLE_PROJECT_USERNAME/$CIRCLE_PROJECT_REPONAME:$TF_VERSION - -workflows: - version: 2 - builder: - jobs: - - build - - release: - requires: - - build - filters: - branches: - only: master diff --git a/.dockerignore b/.dockerignore index 4a027c8..e88192d 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,8 +1,17 @@ .* +AWS/ doc +Dockerfile +*.md +!README.md +*.svg +*.json +*.png +docker-compose.yml providers/ LICENSE examples/ +example/ PowerShell/ BASH/ Kubernetes/ \ No newline at end of file diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000..e5886c6 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,72 @@ +# For most projects, this workflow file will not need changing; you simply need +# to commit it to your repository. +# +# You may wish to alter this file to override the set of languages analyzed, +# or to provide custom queries or build logic. +# +# ******** NOTE ******** +# We have attempted to detect the languages in your repository. Please check +# the `language` matrix defined below to confirm you have the correct set of +# supported CodeQL languages. +# +name: "CodeQL" + +on: + push: + branches: [ "main" ] + pull_request: + # The branches below must be a subset of the branches above + branches: [ "main" ] + schedule: + - cron: '38 19 * * 0' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'javascript', 'python' ] + # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] + # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + # If you wish to specify custom queries, you can do so here or in a config file. + # By default, queries listed here will override any specified in a config file. + # Prefix the list here with "+" to use these queries and those in the config file. + + # Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs + # queries: security-extended,security-and-quality + + + # Autobuild attempts to build any compiled languages (C/C++, C#, or Java). + # If this step fails, then you should remove it and run the build manually (see below) + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + # â„šī¸ Command-line programs to run using the OS shell. + # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun + + # If the Autobuild fails above, remove it and uncomment the following three lines. + # modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance. + + # - run: | + # echo "Run, Build Application using script" + # ./location_of_script_within_repo/buildscript.sh + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000..fe461b4 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,20 @@ +# Dependency Review Action +# +# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging. +# +# Source repository: https://github.com/actions/dependency-review-action +# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v3 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v2 diff --git a/.gitignore b/.gitignore index 47744fc..97b291d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,6 @@ + +*json +*html # Compiled / optimized / DLL files __pycache__/ *.py[cod] @@ -102,6 +105,9 @@ venv.bak/ .vscode .vscode/ +# Embold +.embold/ + # Rope project settings .ropeproject @@ -111,6 +117,9 @@ venv.bak/ # mypy .mypy_cache/ -# Terraform stuff +# Terraform configuration .terraform/ -*.tfstate \ No newline at end of file +*.tfstate + +# Mac +.DS_Store \ No newline at end of file diff --git a/AWS/blast-radius-aws.tf b/AWS/blast-radius-aws.tf index 3ecd782..632b217 100644 --- a/AWS/blast-radius-aws.tf +++ b/AWS/blast-radius-aws.tf @@ -2,19 +2,20 @@ terraform { } provider "aws" { - access_key = var.AWS_ACCESS_KEY_ID - secret_key = var.AWS_SECRET_ACCESS_KEY + # uncomment if global configuration is not set up yet +# access_key = var.AWS_ACCESS_KEY_ID +# secret_key = var.AWS_SECRET_ACCESS_KEY region = var.AWS_REGION } -variable "AWS_ACCESS_KEY_ID" { - default = "" -} - -variable "AWS_SECRET_ACCESS_KEY" { - default = "" -} - +#variable "AWS_ACCESS_KEY_ID" { +# default = "" +#} +# +#variable "AWS_SECRET_ACCESS_KEY" { +# default = "" +#} +# variable "AWS_REGION" { default = "" } diff --git a/Docker.md b/Docker.md new file mode 100644 index 0000000..9b779db --- /dev/null +++ b/Docker.md @@ -0,0 +1,311 @@ +

Docker

+ +[privileges]: https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities +[overlayfs]: https://wiki.archlinux.org/index.php/Overlay_filesystem + +## Table of Contents +- [Preqrequisites](#prerequisites) +- [Run Docker Containers](#run-docker-containers-with-docker-hub-images) +- [Docker Configurations](#docker-configurations) +- [Port Configurations](#port-configurations) +- [Docker Subdirectories](#docker--subdirectories) +- [Image Building](#image-building) + - [Preqrequisites for Buildx](#prerequisites-for-buildx) +- [Shell Scripts](#shell-scripts) +- [Aliases](#aliases) + - [Temporary Aliases](#temporary-aliases) + - [Permanent Aliases](#permanent-aliases) + + +## Prerequisites +* Install Docker + * [Linux](https://docs.docker.com/desktop/install/linux-install/) + * [Mac](https://docs.docker.com/desktop/install/mac-install/) + * [Windows](https://docs.docker.com/desktop/install/windows-install/) + +It is recommended to nstall [Docker Desktop](https://www.docker.com/products/docker-desktop/) as well, a more intuitive GUI for Docker. + +Verify Docker is installed in your Terminal: ```docker info``` + +## Run Docker Containers with Docker Hub Images + +Launch *Blast Radius* for a local directory by manually running: + +> sh, zsh, bash +```sh +docker run --rm -it -p 5000:5000 \ + -v $(pwd):/data:ro \ + --security-opt apparmor:unconfined \ + --cap-add=SYS_ADMIN \ + ianyliu/blast-radius-fork +``` + +> Windows PowerShell +```powershell +docker run --rm -it -p 5000:5000 ` + -v ${pwd}:/data:ro ` + --security-opt apparmor:unconfined ` + --cap-add=SYS_ADMIN ` + ianyliu/blast-radius-fork +``` + +If you do not have the Docker image, it will be automatically pulled for you. You can also build the image yourself +see ([Image Building](#image-building)). + +A slightly more customized variant of this is also available as an example +[docker-compose.yml](./Docker/docker-compose.yml) use case for Workspaces. + +## Docker configurations + +
+ +*Terraform* module links are saved as _absolute_ paths in relative to the +project root (note `.terraform/modules/`). 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`. + +> Note: This is considered a security risk by some, so be sure you understand how this works. + +For more information on how this works and what it means for your host, check +out the [runtime privileges][privileges] documentation. +
+ +## Port configurations + +
+To run the Docker image on a different port, you can modify the Docker command so that PORTNUMBER +maps to the desired port number. + +```sh +docker run --rm -it -p PORTNUMBER:5000 \ + -v $(pwd):/data:ro \ + --security-opt apparmor:unconfined \ + --cap-add=SYS_ADMIN \ + ianyliu/blast-radius-fork +``` + +
+ +## 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 +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/ + `-- .terraform +``` + +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 \ + ianyliu/blast-radius-fork --serve stacks/beef +``` +
+ +## Image Building + +If you'd like to build your own Docker image after making changes to Blast Radius, you can build it in 2 ways: +1. Normal Build + +To execute a normal build, navigate (using commands like `cd`) to the root of your modified Blast Radius project in your terminal. +Make sure you have the Dockerfile in the root of your project. +Now run: + +``` +docker build -t imagename . +``` + +Replace imagename with the name you'd like to give your image. + +Once the build is complete you can run it in the Terraform directory you'd like visualize. + +> sh, zsh, bash +```sh +docker run --rm -it -p 5000:5000 \ + -v $(pwd):/data:ro \ + --security-opt apparmor:unconfined \ + --cap-add=SYS_ADMIN \ + imagename +``` + +> Windows PowerShell +```powershell +docker run --rm -it -p 5000:5000 ` + -v ${pwd}:/data:ro ` + --security-opt apparmor:unconfined ` + --cap-add=SYS_ADMIN ` + imagename +``` + +Go to http://127.0.0.1:5000/ to view the visualization. + +2. Multi-CPU Build + +To build Docker images with multi-architecture support, we will use something known as docker +[buildx](https://docs.docker.com/build/buildx/). + +### Prerequisites for Buildx + +There are 2 ways to set up buildx, the first being insanely easy, while the second being quite complicated. + +1. **Install Docker Desktop>=2.1.0** +Install Docker Desktop [here](https://www.docker.com/products/docker-desktop/). + Then go to `Settings > Docker Engine`. Edit the JSON configuration and change it so that "buildkit" is set to "true". + ![](Docker/Docker-Desktop.png) +2. **Manual Installation** +You will need the following software requirements: +- Docker >= 19.03 +- Experimental mode enabled for Docker CLI + - Set an environment variable: `export DOCKER_CLI_EXPERIMENTAL=enabled` + - Edit config file at `$HOME/.docker/config.json`: `{"experimental": "enabled"}` +- Linux kernel >= 4.8 or fix-binary (F) flag support on the kernel side of binfmt_misc +- binfmt_misc file system mounted +- Host or Docker image based installation of: + - Host installation + - QEMU installation + - binfmt-support package >= 2.1.7 + - Docker image-based installation + - A Docker image containing both QEMU binaries and set up scripts that register QEMU in binfmt_misc + +For more details on manual installation see +[this Medium article](https://medium.com/@artur.klauser/building-multi-architecture-docker-images-with-buildx-27d80f7e2408). + +Check that buildx is installed: `docker buildx` + +Now we need to create a buildx builder + +`docker buildx create --name mybuilder` + +and use the builder + +`docker buildx use mybuilder` + +View your new builder: `docker buildx ls` + +As of 2022, buildx can export the image locally or to a Docker registry. + +However, local image loading is only supported for single-architecture images. +To use multi-architecture images, we will need to push to a Docker registry. + +To use a Docker registry, we need to first login using +`docker login`. +If you don't have a Docker account yet, you can create one +[here](https://hub.docker.com/). + +Navigate to the directory where the `Dockerfile` is located (download the repo via Git/GitHub if you haven't already). +Now we can build the image. + +```sh +docker buildx build \ +--platform \ +linux/arm64,linux/amd64,linux/amd64/v2,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6 \ +-t imagename \ +--push . +``` + +Run the image (replace USERNAME and imagename accordingly) +```sh +docker run --rm -it -p 5000:5000 \ + -v $(pwd):/data:ro \ + --security-opt apparmor:unconfined \ + --cap-add=SYS_ADMIN \ + USERNAME/imagename +``` + +> Note: Architectures `linux/riscv64,linux/mips64le,linux/mips64` are supported by buildx, +but the image of Python Alpine does not usually support these architectures. +> Note: If in the future local loading of Docker images is supported, replace `--push` with `--load` + + +## Shell Scripts +In the [PowerShell folder](PowerShell) and [BASH folder](BASH) there are Docker build and run shell scripts. +Using shell scripts makes running and building the Docker containers easier and less error prone. + +Here's an example of running the docker Shell script for running a container. + +```sh +cd blast-radius-fork +/bin/bash ./docker_run.sh +``` + +Compare that to + +```sh +docker run --rm -it -p 5000:5000 \ + -v $(pwd):/data:ro \ + --security-opt apparmor:unconfined \ + --cap-add=SYS_ADMIN \ + blast-radius-fork +``` + +## Aliases + +An alias in Linux is a shortcut to a command. They are usually used to replace long commands. +To see what aliases you have, run `alias`. + +There are 2 types of aliases. Temporary ones and permanent ones. + +#### Temporary Aliases + +To creat temporary aliases, simply follow the formula of ```alias SHORTCUT='COMMAND'```. Here's an example of a clear +command referenced by `c`: `alias c='clear'` + +Let's say we want to use `br-docker` to replace the long Docker run command. + +```sh +alias br-docker='docker run --rm -it -p 5000:5000 \ +-v $(pwd):/data:ro \ + --security-opt apparmor:unconfined \ + --cap-add=SYS_ADMIN \ + ianyliu/blast-radius-fork' +``` +Now we can just run `br-docker` whenever we want to run a Docker container to start Blast Radius! + +Here's another example using [Shell scripts](#shell-scripts). +```sh +alias br-build='/bin/bash /Users/USERNAME/blast-radius-fork/BASH/docker_build.sh' +``` +Now we can build our Docker image by just using `br-build`! + +#### Permanent Aliases + +To create permanent aliases, one needs to add it to their shell configuration file. + +* PowerShell configuration files are usually located in `$PSHOME` +* BASH: `~/.bashrc` +* ZSH: `~/.zshrc` +* FISH: `~/.config/fish/config.fish` + +Now open the shell config file in a text editor. +Example: `sudo vi ~/.bashrc` + +Go to the aliases section, and add your aliases. +Here's a helpful +[article](https://phoenixnap.com/kb/linux-alias-command#:~:text=In%20Linux%2C%20an%20alias%20is,and%20avoiding%20potential%20spelling%20errors.). \ No newline at end of file diff --git a/Docker/Docker-Desktop.png b/Docker/Docker-Desktop.png new file mode 100644 index 0000000..cb317c0 Binary files /dev/null and b/Docker/Docker-Desktop.png differ diff --git a/Dockerfile b/Dockerfile index bb89200..3cfbc9c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,10 +1,10 @@ -ARG TF_VERSION=1.2.5 -ARG PYTHON_VERSION=3.8 +ARG TF_VERSION=1.3.3 +ARG PYTHON_VERSION=3.10 FROM hashicorp/terraform:$TF_VERSION AS terraform FROM python:$PYTHON_VERSION-alpine -RUN pip install -U pip ply \ +RUN pip install -U --no-cache-dir pip ply \ && apk add --update --no-cache graphviz ttf-freefont \ && apk upgrade @@ -16,8 +16,9 @@ WORKDIR /src COPY . . RUN pip install -e . +# comment out 2 lines below to optimize build speed WORKDIR /data RUN echo $(timeout 15 blast-radius --serve --port 5001; test $? -eq 124) > /output.txt ENTRYPOINT ["/bin/docker-entrypoint.sh"] -CMD ["blast-radius", "--serve"] +CMD ["blast-radius", "--serve"] \ No newline at end of file diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 6eefab5..0000000 --- a/MANIFEST.in +++ /dev/null @@ -1,9 +0,0 @@ -include * -include blastradius/server/static/css/* -include blastradius/server/static/js/* -include blastradius/server/example/demo-1/* -include blastradius/server/example/demo-2/* -include blastradius/server/example/demo-3/* -include blastradius/server/templates/* -include blastradius/doc/* -include blastradius/utilities/providers/* diff --git a/Makefile b/Makefile deleted file mode 100644 index 65bf3e3..0000000 --- a/Makefile +++ /dev/null @@ -1,45 +0,0 @@ -# -# make clean -# make -# make publish -# -# TODO: add tests. -# - -CATEGORIES_JSON = ./blastradius/server/static/js/categories.json -CATEGORIES_JS = ./blastradius/server/static/js/categories.js - -.PHONY: clean -clean: - -find . -type d -name __pycache__ -exec rm -r {} \+ - -rm $(CATEGORIES_JSON) - -rm $(CATEGORIES_JS) - -# build pypi package -.PHONY: dist -dist: - -python3 setup.py sdist - -# build docker image -.PHONY: docker -docker: - -docker build -t ianyliu/blast-radius-fork . - -# push pypi and docker images to public repos -.PHONY: publish -publish: - -twine upload dist/* - -docker push ianyliu/blast-radius-fork:latest - -# rebuild categories.js from upstream docs -.PHONY: categories -categories: $(CATEGORIES_JS) - -$(CATEGORIES_JSON): - -./utilities/providers/provider-category-json.py > $(CATEGORIES_JSON).new && mv $(CATEGORIES_JSON).new $(CATEGORIES_JSON) - -$(CATEGORIES_JS): $(CATEGORIES_JSON) - -sed -e '1s/{/resource_groups \= {/' $(CATEGORIES_JSON) > $(CATEGORIES_JS).new && mv $(CATEGORIES_JS).new $(CATEGORIES_JS) - -# probably best to clean 1st -all: categories dist docker \ No newline at end of file diff --git a/PowerShell/docker_build.ps1 b/PowerShell/docker_build.ps1 index f8911e8..e998329 100644 --- a/PowerShell/docker_build.ps1 +++ b/PowerShell/docker_build.ps1 @@ -1,4 +1,8 @@ -& docker buildx build -f ..\Dockerfile ` ---platform ` -linux/arm64,linux/amd64,linux/amd64/v2,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6 ` --t blast-radius-fork ../ \ No newline at end of file +& docker build -f ..\Dockerfile ` +-t blast-radius-fork ../ + +#Multi-cpu build +#& docker buildx build -f ..\Dockerfile ` +#--platform ` +#linux/arm64,linux/amd64,linux/amd64/v2,linux/ppc64le,linux/s390x,linux/386,linux/arm/v7,linux/arm/v6 ` +#-t blast-radius-fork --push ../ \ No newline at end of file diff --git a/README.md b/README.md index 16421bb..d40372f 100644 --- a/README.md +++ b/README.md @@ -1,28 +1,30 @@

Blast Radius

-[![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/ +[docs]: https://28mm.github.io/blast-radius-docs/ + +_Blast Radius Fork_ is an interactive visualizer for [Terraform](https://www.terraform.io/) based off of +[_Blast Radius_](https://28mm.github.io/blast-radius/), +which hasn't been actively maintained since 2020. -_Blast Radius_ is a tool for reasoning about [Terraform](https://www.terraform.io/) dependency graphs -with interactive visualizations. +It is a work in progress and is not guaranteed to be bug free. Please feel free to contribute! ---------------------------------- ## Table of Contents - [Usage](#usage) -- [Preqrequisites](#prerequisites) -- [Quickstart](#quickstart) -- [Docker](#docker) - - [Docker Configurations](#docker-configurations) - - [Docker Subdirectories](#docker--subdirectories) -- [Kubernetes](#kubernetes) +- [Preqrequisites](#prerequisites-for-local-use) +- [Local Quickstart](#local-quickstart) +- [Docker Quickstart](#docker-quickstart) +- [Kubernetes Quickstart](#kubernetes-quickstart) - [Kubernetes Prerequisites](#kubernetes-prerequisites) - [Start App on Kubernetes](#start-the-app-on-kubernetes) - [Kubernetes Debugging & Helpful Commands](#kubernetes-debugginghelpful-commands) +- [Parameters](#parameters) - [Embedded Figures](#embedded-figures) - [How It Works](#how-it-works) +- [What's Different](#whats-different) - [Future Implementation Possibilities](#future-implementations--possible-functionalities) - [Further Reading](#further-reading) - [Other Tools to Check Out](#other-tools-to-check-out) @@ -41,16 +43,19 @@ Use _Blast Radius_ to: ![screenshot](doc/blastradius-interactive.png) -## Prerequisites +## Prerequisites for Local Use +* [Python](https://www.python.org/) 3.7+ * [Graphviz](https://www.graphviz.org/) -* [Python](https://www.python.org/) 3.7-3.9 (does not work with Python 3.10 on Ubuntu machines) +* [Terraform](https://www.terraform.io/) (if you do not have generated Terraform DOT graphs yet) > __Note:__ For macOS you can `brew install graphviz` + +> __Note:__ For Docker usage prerequisites, see [Docker.md](Docker.md) -## Quickstart +## Local Quickstart -The fastest way to get up and running with *Blast Radius* is to install it with +The fastest way to run with *Blast Radius* is to install it with `pip` to your pre-existing environment: ```sh @@ -61,30 +66,41 @@ or python3 -m pip install git+https://github.com/Ianyliu/blast-radius-fork ``` -If you have an initialized *Terraform* directory, you can just start *Blast Radius* within the initialized *Terraform* -directory: +You can then run Blast Radius from the command line: ```sh +blast-radius --serve +``` + +If you want to create graphs for an initialized *Terraform* directory, you can just start *Blast Radius* within the +initialized *Terraform* +directory: + +``` blast-radius --serve /path/to/terraform/directory ``` And you will shortly be rewarded with a browser link http://127.0.0.1:5000/. -If you __DON'T__ have an initialized *Terraform* directory and would like to start it as a standalone application to visualize existing DOT files, you can start it in any directory: -```sh -blast-radius --serve -``` -You may then upload DOT script via text input or file upload. +[//]: # (You can specify the port number with the `--port` flag:) + +[//]: # () +[//]: # (```) + +[//]: # (blast-radius --serve /path/to/terraform/directory --port=8080) + +[//]: # (```) -Other ways to run it include [Docker](#docker) and [Kubernetes](#kubernetes) +Other ways to run it include [Docker](#docker-quickstart) and [Kubernetes](#kubernetes-quickstart) -## Docker +## Docker Quickstart [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: +Launch a container for a local directory with *Blast Radius* running: +sh, zsh, bash, etc. (Linux recommended): ```sh docker run --rm -it -p 5000:5000 \ -v $(pwd):/data:ro \ @@ -93,66 +109,21 @@ docker run --rm -it -p 5000:5000 \ ianyliu/blast-radius-fork ``` -A slightly more customized variant of this is also available as an example -[docker-compose.yml](./Docker/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/`). 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 -out the [runtime privileges][privileges] documentation. -
- -#### 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 -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/ - `-- .terraform +Windows PowerShell: +```powershell +docker run --rm -it -p 5000:5000 ` + -v ${pwd}:/data:ro ` + --security-opt apparmor:unconfined ` + --cap-add=SYS_ADMIN ` + ianyliu/blast-radius-fork ``` -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: +A slightly more customized variant of this is also available as an example +[docker-compose.yml](./Docker/docker-compose.yml) usecase for Workspaces. -```sh -$ cd project -$ docker run --rm -it -p 5000:5000 \ - -v $(pwd):/data:ro \ - --security-opt apparmor:unconfined \ - --cap-add=SYS_ADMIN \ - ianyliu/blast-radius-fork --serve stacks/beef -``` -
+For more details on Docker usage, see [Docker.md](Docker.md) -## Kubernetes +## Kubernetes Quickstart Launch *Kubernetes* locally using Minikube, Kubernetes, and Kubectl: @@ -160,7 +131,7 @@ Launch *Kubernetes* locally using Minikube, Kubernetes, and Kubectl:
-* Docker or another container or virtual machine manager +* Docker (or another container or virtual machine manager) * Kubectl: https://kubernetes.io/docs/tasks/tools/ * Minikube: https://minikube.sigs.k8s.io/docs/start/
@@ -171,12 +142,13 @@ Launch *Kubernetes* locally using Minikube, Kubernetes, and Kubectl: 1. Start Minikube ```minikube start``` -2. Change directories to the file containing the 2 YAML files (*k8-blast-radius-deployment.yaml* and *k8-blast-radius-service.yaml* pply the YAML configuration files to the default namespace (or any other namespace) +2. Change directories to the file containing the 2 YAML files (*k8-blast-radius-deployment.yaml* and +3. *k8-blast-radius-service.yaml* apply the YAML configuration files to the default namespace (or any other namespace) ``` kubectl apply -f k8-blast-radius-deployment.yaml kubectl apply -f k8-blast-radius-service.yaml ``` -3. Access the app +Access the app ``` minikube service k8-blast-radius-service ``` @@ -196,6 +168,26 @@ minikube service k8-blast-radius-service ```minikube dashboard``` +## Parameters +* Directory: Defaults to `$PWD` or current directory. The directory in which to look for Terraform files. +This is required if the user wants to use a Terraform project as input +(instead of uploading a file or pasting DOT script). +* `--port`: Defaults to 5000. The port to access the app (http://localhost:PORT) +Any valid localhost port is allowed. +* `--serve`: Starts a webserver locally with Terraform's interactive graph +* `--json`: Prints a JSON representation of a Terraform graph. The JSON has 2 items, `edges` and `nodes`. +* `--dot`: Returns a string consisting of Graphviz DOT script of graph. (no colors) +* `--svg`: Prints SVG representation of graph (with colors). +* `--graph`: +* `--module-depth`: Takes an integer as input and only eliminates display of deeply nested modules. +This will not show every node on the graph unless the user specifies a depth larger than the graph. +* `--focus`: Show only specified resource and its dependencies. Not available in web app. Only works with `--json` and `--svg`. + * Example: ```terraform graph | blast-radius --focus \ + "[root] module.us-west-2.module.secondary_subnet.data.aws_vpc.target" --svg``` +* `--center`: Prunes the graph to a subgraph (same thing as red button in web app). Only works with `--json` and `--svg`. + * Example: ```terraform graph | blast-radius --center \ + "[root] module.us-west-2.module.secondary_subnet.data.aws_vpc.target" --svg``` + ## Embedded Figures You may wish to embed figures produced with *Blast Radius* in other documents. @@ -215,21 +207,40 @@ You can read more details in the [documentation for embedded figures](doc/embedd - [d3.js](https://d3js.org/) to implement interactive features - [Flask](https://flask.palletsprojects.com/) to start a server - [Vanilla JavaScript](http://vanilla-js.com/) and [jQuery](https://jquery.com/) for front-end functionality -- [HTML](https://html.com/), [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS), [Bootstrap](https://getbootstrap.com/), and other libraries for front-end design +- [HTML](https://html.com/), [CSS](https://developer.mozilla.org/en-US/docs/Web/CSS), +- [Bootstrap](https://getbootstrap.com/), and other libraries for front-end design -## Motivation -The original creator of this open source project, [Patrick McMurchie](https://github.com/28mm), has been inactive on this project for some time. -There are many issues waiting to be resolved, and features to be added. This repository presents some basic modifications, additional features, and enhanced accessibility. +Terraform generates graphs in the form of [DOT](https://en.wikipedia.org/wiki/DOT_language) language. *Blast Radius* +uses [Graphviz](https://graphviz.org/) to layout the graph after converting to SVG, +and D3.js to implement interactive features. +Terraform configurations are then parsed by [python-hcl2](https://github.com/amplify-education/python-hcl2) to generate +a [JSON](https://en.wikipedia.org/wiki/JSON_document) representation of the graph, +which provides details of each resource on hover. +All of this is hosted on [Flask](https://flask.palletsprojects.com/) and runs on a [local server](http://localhost:5000/). -## Modifications & New Features -* Independence from Terraform and Terraform files - * App can run on its own, accepting file or keyboard input +## Motivation +The original creator of this open source project, [Patrick McMurchie](https://github.com/28mm), has been inactive on +this project for some time. +There are many issues waiting to be resolved, and features to be added. This repository presents some +**basic modifications**, **additional features**, and **enhanced accessibility**. + +## What's Different +* **Independence** from Terraform and Terraform files + * App can run on its own, accepting DOT file or keyboard input * Multi-graph feature - * The app can display multiple graphs and can be compared side by side with tabs + * The app can **display multiple graphs** and can be compared side by side with tabs * Print * The graph can be printed, although the print can sometimes cut off the graph at times * UI changes * To enable a better design, the multi-colored buttons and other parts of the page have been changed to follow the 60-30-10 design rule +* Compatability with recent versions of Terraform, Python, and Python packages +* Created a new Docker image at [ianyliu/blast-radius-fork](https://hub.docker.com/repository/docker/ianyliu/blast-radius-fork/) for multi-cpu architectures equipped with updated features +* Added Shell scripts that can be used to run & build the Docker image with aliases for convenience +* Updated README.md +* Integrated changes across other forks and pull requests of Blast Radius, including: + * PowerShell scripts for running and building Docker containers + * Running Terratests during Docker build + * Allowing Blast Radius to run even if JSON data couldn't be parsed ## Future Implementations & Possible Functionalities * Accept file input as a command-line argument @@ -239,6 +250,9 @@ There are many issues waiting to be resolved, and features to be added. This rep * Allow upload of multiple files and folders * Drag and drop file upload * Dark mode +* Support for Terragrunt +* Support for Tfenv +* Compress Docker image size (currently 180+MB) * Editable tab names * Reorder tabs via drag * Responsive webpage @@ -250,17 +264,17 @@ There are many issues waiting to be resolved, and features to be added. This rep * PyInstaller * Mobile interface formatting * Loading spinner before graphs load (and disable buttons) -* cache DOT script or SVG in local storage so it can be loaded next time without re-upload +* Cache DOT script or SVG in local storage so it can be loaded next time without re-upload * Animation * Shows difference between current state and state after apply * Shows difference between one Terraform graph and another via animation -* Add example Terraform files that allow Blast Radius to be run on Microsoft Azure, Google Cloud, IBM Cloud Services, etc. +* Add example Terraform DOT files that allow Blast Radius to be run on Microsoft Azure, Google Cloud, IBM Cloud Services, etc. * Integration with Neo4j or other graph database, parse *Terraform* files and find relationships between resources ## Further Reading -The development of *Blast Radius* is documented in a series of +The original development of *Blast Radius* is documented in a series of [blog](https://28mm.github.io) posts by the original creator: * [part 1](https://28mm.github.io/notes/d3-terraform-graphs): motivations, d3 force-directed layouts vs. vanilla graphviz. @@ -281,6 +295,18 @@ with various *Terraform* providers, and aren't necessarily ideal. Additional examples, particularly demonstrations of best-practices, or of multi-cloud configurations strongly desired. +There are more 188 forks as of August 2022, each containing new updates or features of some sort. Notable ones include: +- https://github.com/gruberdev/blast-radius/ +- https://github.com/IBM-Cloud/blast-radius/ +- https://github.com/nishubharti/blast-radius/ +- https://github.com/obourdon/blast-radius/ +- https://github.com/nibhart1/blast-radius/ + +An alternate working Docker image for Blast Radius is https://hub.docker.com/r/grubertech/blast-radius + + +It would greatly help if you could contribute to bringing all of these forks into one repository so that we can have a tool that can be used by everyone. + ## Other Tools to Check Out [Inframap]: https://github.com/cycloidio/inframap @@ -288,18 +314,33 @@ configurations strongly desired. [Terraform Visual]: https://github.com/hieven/terraform-visual [Rover]: https://github.com/im2nguyen/rover [Pluralith]: https://www.pluralith.com/ +* [Pluralith] + * "_A tool for Terraform state visualisation and automated generation of infrastructure documentation_" + * Written in: Golang + * Pros + * Change Highlighting + * Apply plan within application + * Cost information + * Provides granular details on click + * Plan-to-plan comparison (tabs) + * Filter (by Created, Destroyed, Updated, Recreated) + * GUI (Graphical User Interface) + * Lots more features... there's so many! + * Cons + * More advanced features cost money (understandably) + * Newer, with less tutorials and tests * [Inframap] - * "Read your tfstate or HCL to generate a graph specific for each provider, showing only the resources that are most important/relevant." + * "_Read your tfstate or HCL to generate a graph specific for each provider, showing only the resources that are most important/relevant._" * Input: tfstate or HCL * Written in: Golang * Pros: - * Works directly with Terraform state files or .tf files + * Works directly with Terraform state files or .tf files, instead of DOT input * Docker * Simplifies graph * Cons: * Cannot provide more detail, oversimplification * [Terraform Graph Beautifier] - * "Terraform graph beautifier" + * "_Terraform graph beautifier_" * Input: DOT script output from ```terraform graph``` command in Terraform init directory * Written in: Golang * Pros @@ -307,7 +348,7 @@ configurations strongly desired. * Cons * Requires Terraform init directory and Terraform installation * [Terraform Visual] - * "Terraform Visual is an interactive way of visualizing your Terraform plan" + * "_Terraform Visual is an interactive way of visualizing your Terraform plan_" * Input: Terraform JSON plan files * Written in: TypeScript, JavaScript, CSS * Pros @@ -315,7 +356,7 @@ configurations strongly desired. * Creates HTML page that you can save later * Has online version: https://hieven.github.io/terraform-visual/ (so doesn't require local installation) * [Rover] - * "Interactive Terraform visualization. State and configuration explorer." + * "_Interactive Terraform visualization. State and configuration explorer._" * Inputs: Terraform files in a directory or provided plan file * Written in: Golang, VueJS * Pros @@ -325,18 +366,3 @@ configurations strongly desired. * Docker compatible * Cons * Requires Terraform directory to be init, or else it will not work (even in Docker it also needs init) -* [Pluralith] - * "A tool for Terraform state visualisation and automated generation of infrastructure documentation" - * Written in: Golang - * Pros - * Change Highlighting - * Apply plan within application - * Cost information - * Provides granular details on click - * Plan-to-plan comparison (tabs) - * Filter (by Created, Destroyed, Updated, Recreated) - * GUI (Graphical User Interface) - * Lots more features... there's so many! - * Cons - * More advanced features cost money (understandably) - * New and less tested diff --git a/blastradius/__init__.py b/bin/blastradius/__init__.py similarity index 100% rename from blastradius/__init__.py rename to bin/blastradius/__init__.py diff --git a/blastradius/graph.py b/bin/blastradius/graph.py similarity index 100% rename from blastradius/graph.py rename to bin/blastradius/graph.py diff --git a/blastradius/handlers/__init__.py b/bin/blastradius/handlers/__init__.py similarity index 100% rename from blastradius/handlers/__init__.py rename to bin/blastradius/handlers/__init__.py diff --git a/blastradius/handlers/apply.py b/bin/blastradius/handlers/apply.py similarity index 100% rename from blastradius/handlers/apply.py rename to bin/blastradius/handlers/apply.py diff --git a/blastradius/handlers/dot.py b/bin/blastradius/handlers/dot.py similarity index 100% rename from blastradius/handlers/dot.py rename to bin/blastradius/handlers/dot.py diff --git a/blastradius/handlers/plan.py b/bin/blastradius/handlers/plan.py similarity index 100% rename from blastradius/handlers/plan.py rename to bin/blastradius/handlers/plan.py diff --git a/blastradius/handlers/terraform.py b/bin/blastradius/handlers/terraform.py similarity index 61% rename from blastradius/handlers/terraform.py rename to bin/blastradius/handlers/terraform.py index e347d61..fd57e4d 100644 --- a/blastradius/handlers/terraform.py +++ b/bin/blastradius/handlers/terraform.py @@ -18,15 +18,21 @@ def __init__(self, directory=None, settings=None): self.settings = settings if settings else {} # handle the root module first... - self.directory = directory if directory else os.getcwd() + self.directory = os.path.abspath(directory) if directory else os.getcwd() #print(self.directory) + self.config = {} self.config_str = '' iterator = iglob( self.directory + '/*.tf') for fname in iterator: with open(fname, 'r', encoding='utf-8') as f: - self.config_str += f.read() + ' ' - config_io = io.StringIO(self.config_str) - self.config = hcl.load(config_io) + try: + contents = f.read() + self.config_str += contents + ' ' + raw = io.StringIO(contents) + parsed = hcl.load(raw) + self.config.update(parsed) + except Exception as e: + raise RuntimeError('Exception occurred while parsing ' + fname) from e # then any submodules it may contain, skipping any remote modules for # the time being. @@ -36,41 +42,44 @@ def __init__(self, directory=None, settings=None): if 'source' not in mod: continue source = mod['source'][0] - # '//' used to refer to a subdirectory in a git repo - if re.match(r'.*\/\/.*', source): - continue - # '@' should only appear in ssh urls - elif re.match(r'.*\@.*', source): - continue - # 'github.com' special behavior. - elif re.match(r'github\.com.*', source): - continue - # points to new TFE module registry - elif re.match(r'app\.terraform\.io', source): - continue - # bitbucket public and private repos - elif re.match(r'bitbucket\.org.*', source): - continue - # git::https or git::ssh sources - elif re.match(r'^git::', source): - continue - # git:// sources - elif re.match(r'^git:\/\/', source): - continue - # Generic Mercurial repos - elif re.match(r'^hg::', source): - continue - # Public Terraform Module Registry - elif re.match(r'^[a-zA-Z0-9\-_]+\/[a-zA-Z0-9\-_]+\/[a-zA-Z0-9\-_]+', source): - continue - # AWS S3 buckets - elif re.match(r's3.*\.amazonaws\.com', source): - continue + + # # '//' used to refer to a subdirectory in a git repo + # if re.match(r'.*\/\/.*', source): + # continue + # # '@' should only appear in ssh urls + # elif re.match(r'.*\@.*', source): + # continue + # # 'github.com' special behavior. + # elif re.match(r'github\.com.*', source): + # continue + # # points to new TFE module registry + # elif re.match(r'app\.terraform\.io', source): + # continue + # # bitbucket public and private repos + # elif re.match(r'bitbucket\.org.*', source): + # continue + # # git::https or git::ssh sources + # elif re.match(r'^git::', source): + # continue + # # git:// sources + # elif re.match(r'^git:\/\/', source): + # continue + # # Generic Mercurial repos + # elif re.match(r'^hg::', source): + # continue + # # Public Terraform Module Registry + # elif re.match(r'^[a-zA-Z0-9\-_]+\/[a-zA-Z0-9\-_]+\/[a-zA-Z0-9\-_]+', source): + # continue + # # AWS S3 buckets + # elif re.match(r's3.*\.amazonaws\.com', source): + # continue + + if source == '.': + continue # avoid infinite recursion path = os.path.join(self.directory, source) if os.path.exists(path): # local module - # fixme path join. eek. self.modules[name] = Terraform(directory=path, settings=mod) else: # remote module diff --git a/blastradius/server/__init__.py b/bin/blastradius/server/__init__.py similarity index 100% rename from blastradius/server/__init__.py rename to bin/blastradius/server/__init__.py diff --git a/blastradius/server/server.py b/bin/blastradius/server/server.py similarity index 91% rename from blastradius/server/server.py rename to bin/blastradius/server/server.py index 52aa54f..ffb1e7f 100644 --- a/blastradius/server/server.py +++ b/bin/blastradius/server/server.py @@ -31,7 +31,7 @@ def index(): # we need terraform, graphviz, and an init-ed terraform project. if not which('terraform') and not which('terraform.exe'): is_terraform_installation = False - if not (os.path.exists('.terraform') and tf_data_dir is not None and os.path.exists(tf_data_dir)): + if not os.path.exists('.terraform') and not (tf_data_dir is not None and os.path.exists(tf_data_dir)): is_terraform_directory = False if not which('dot') and not which('dot.exe'): #Return error page. Graphviz is a dependency that has to exist. @@ -45,9 +45,11 @@ def index(): if is_terraform_directory is False or is_terraform_installation is False: # Blast Radius template without default graph + print("Blast Radius could not find a Terraform directory ") if is_terraform_directory is False else print("Blast Radius could not find a Terraform installation. ") template = 'non_tf_dir.html' else: # Blast Radius template with default graph + print("Blast Radius is generating graphs for your Terraform directory. ") template = 'index.html' #Run Blast Radius presenting a default graph @@ -195,9 +197,9 @@ def graph_json(): def run_tf_graph(): - completed = subprocess.run(['terraform', 'graph'], stdout=subprocess.PIPE) + completed = subprocess.run(['terraform', 'graph'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) if completed.returncode != 0: - raise + raise Exception('Execution error', completed.stderr) return completed.stdout.decode('utf-8') @@ -247,8 +249,14 @@ def get_terraform_exe(): def get_python_version(): + completed = subprocess.run( - ['python', '--version'], stdout=subprocess.PIPE) + ['python3', '--version'], stdout=subprocess.PIPE) + if completed.returncode != 0: - raise + print("'python3' was not found, trying again with 'python' ... ") + completed2 = subprocess.run( + ['python', '--version'], stdout=subprocess.PIPE) + if completed2.returncode != 0: + raise return completed.stdout.decode('utf-8').splitlines()[0].split(' ')[-1] diff --git a/blastradius/server/static/css/bootstrap.min.css b/bin/blastradius/server/static/css/bootstrap.min.css similarity index 100% rename from blastradius/server/static/css/bootstrap.min.css rename to bin/blastradius/server/static/css/bootstrap.min.css diff --git a/blastradius/server/static/css/selectize.css b/bin/blastradius/server/static/css/selectize.css similarity index 100% rename from blastradius/server/static/css/selectize.css rename to bin/blastradius/server/static/css/selectize.css diff --git a/blastradius/server/static/css/style.css b/bin/blastradius/server/static/css/style.css similarity index 100% rename from blastradius/server/static/css/style.css rename to bin/blastradius/server/static/css/style.css diff --git a/blastradius/server/static/example/demo-1/demo-1.json b/bin/blastradius/server/static/example/demo-1/demo-1.json similarity index 100% rename from blastradius/server/static/example/demo-1/demo-1.json rename to bin/blastradius/server/static/example/demo-1/demo-1.json diff --git a/blastradius/server/static/example/demo-1/demo-1.svg b/bin/blastradius/server/static/example/demo-1/demo-1.svg similarity index 100% rename from blastradius/server/static/example/demo-1/demo-1.svg rename to bin/blastradius/server/static/example/demo-1/demo-1.svg diff --git a/blastradius/server/static/example/demo-2/demo-2.json b/bin/blastradius/server/static/example/demo-2/demo-2.json similarity index 100% rename from blastradius/server/static/example/demo-2/demo-2.json rename to bin/blastradius/server/static/example/demo-2/demo-2.json diff --git a/blastradius/server/static/example/demo-2/demo-2.svg b/bin/blastradius/server/static/example/demo-2/demo-2.svg similarity index 100% rename from blastradius/server/static/example/demo-2/demo-2.svg rename to bin/blastradius/server/static/example/demo-2/demo-2.svg diff --git a/blastradius/server/static/example/demo-3/demo-3.json b/bin/blastradius/server/static/example/demo-3/demo-3.json similarity index 100% rename from blastradius/server/static/example/demo-3/demo-3.json rename to bin/blastradius/server/static/example/demo-3/demo-3.json diff --git a/blastradius/server/static/example/demo-3/demo-3.svg b/bin/blastradius/server/static/example/demo-3/demo-3.svg similarity index 100% rename from blastradius/server/static/example/demo-3/demo-3.svg rename to bin/blastradius/server/static/example/demo-3/demo-3.svg diff --git a/blastradius/server/static/js/blast-radius.js b/bin/blastradius/server/static/js/blast-radius.js similarity index 95% rename from blastradius/server/static/js/blast-radius.js rename to bin/blastradius/server/static/js/blast-radius.js index 7d072ca..9229fd3 100644 --- a/blastradius/server/static/js/blast-radius.js +++ b/bin/blastradius/server/static/js/blast-radius.js @@ -25,7 +25,7 @@ build_uri = function (url, params) { url += '?' for (var key in params) url += key + '=' + params[key] + '&'; - return url.slice(0,-1); + return url.slice(0, -1); } let uploadRequest = (url, formData, selector) => { @@ -54,20 +54,6 @@ let uploadFile = function (file, tabNumber) { let formData = new FormData(); formData.set('file', file); uploadRequest('/upload', formData, selector) - - // fetch('/upload', { - // method: "POST", - // body: formData - // }) - // .then(response => (response.json())) - // .then(async function (resjson) { - // let br_state = { - // selector: {} - // } - // xml = $.parseXML(resjson.SVG); - // json = JSON.parse(resjson.JSON); - // await blastradius(selector, '/graph.svg', '/graph.json', br_state, xml, json) - // }) } else { alert("This is not a valid File!"); } @@ -78,7 +64,7 @@ let inputGraph = async () => { if (graphinput != null) { let lastTabContent = $("div.tabcontent").last()[0] - if (lastTabContent != null ) { + if (lastTabContent != null) { let prevNumber = parseInt(lastTabContent.id.split("-")[1]) let curNumber = parseInt(prevNumber) + 1 let selector = "#graph-" + curNumber; @@ -264,7 +250,6 @@ let insertTabContent = (prevNumber) => { let newTabGraph = '
' $('.drag-area').append(newTabContentDiv); $(`#tab-${curNum}`).append(topNavBar, newTabGraph); - // console.log($(`#tab-${curNum}`).children("nav").children("ul").children("li").last().children("div.dropdown").children("button.btn.btn-info.dropdown-toggle").first()[0].id) } @@ -295,12 +280,12 @@ Queue.prototype.dequeue = function () { var oldestIndex = this._oldestIndex, newestIndex = this._newestIndex, deletedData; - + if (oldestIndex !== newestIndex) { deletedData = this._storage[oldestIndex]; delete this._storage[oldestIndex]; this._oldestIndex++; - + return deletedData; } }; @@ -335,8 +320,6 @@ blastradius = function (selector, svg_url, json_url, br_state = {}, uploadXML = var color = (state['color'] ? state['color'] : d3.scaleOrdinal(d3['schemeCategory20'])); state['color'] = color; - //console.log(state); - // 1st pull down the svg, and append it to the DOM as a child // of our selector. If added as , we wouldn't // be able to manipulate x.svg with d3.js, or other DOM fns. @@ -375,28 +358,24 @@ blastradius = function (selector, svg_url, json_url, br_state = {}, uploadXML = data = uploadJSON } - if (!error) { - var edges = data.edges; - var svg_nodes = []; - var nodes = {}; - data.nodes.forEach(function (node) { - if (!(node.type in resource_groups)) + if (error) { + console.error("No Terraform files were found, so JSON details will not be available. The graph is still usable but without all features enabled such as filtering content"); + // alert("No Terraform files were found, so JSON details will not be available. The graph is still usable but without all features enabled such as filtering content"); + } + + // if (!error) { + var edges = data.edges; + var svg_nodes = []; + var nodes = {}; + data.nodes.forEach(function (node) { + if (!(node.type in resource_groups)) if (node.label === '[root] root') { // FIXME: w/ tf 0.11.2, resource_name not set by server. node.resource_name = 'root'; } - node.group = (node.type in resource_groups) ? resource_groups[node.type] : -1; - nodes[node['label']] = node; - svg_nodes.push(node); - }); - } else { - console.log("An error occurred when parsing JSON data for resource descriptions"); - let div = document.createElement("div"); - div.setAttribute("role", "alert"); - div.classList = ["alert alert-danger"]; - div.textContent = "A server exception has occurred. The graph is still usable but without all features enabled such as filtering content" - document.getElementsByClassName("navbar")[0].appendChild(div); - edges = [] - } + node.group = (node.type in resource_groups) ? resource_groups[node.type] : -1; + nodes[node['label']] = node; + svg_nodes.push(node); + }); // convenient to access edges by their source. diff --git a/blastradius/server/static/js/bootstrap.min.js b/bin/blastradius/server/static/js/bootstrap.min.js similarity index 100% rename from blastradius/server/static/js/bootstrap.min.js rename to bin/blastradius/server/static/js/bootstrap.min.js diff --git a/blastradius/server/static/js/categories.js b/bin/blastradius/server/static/js/categories.js similarity index 100% rename from blastradius/server/static/js/categories.js rename to bin/blastradius/server/static/js/categories.js diff --git a/blastradius/server/static/js/categories.json b/bin/blastradius/server/static/js/categories.json similarity index 100% rename from blastradius/server/static/js/categories.json rename to bin/blastradius/server/static/js/categories.json diff --git a/blastradius/server/static/js/d3-tip.js b/bin/blastradius/server/static/js/d3-tip.js similarity index 100% rename from blastradius/server/static/js/d3-tip.js rename to bin/blastradius/server/static/js/d3-tip.js diff --git a/blastradius/server/static/js/d3.v4.js b/bin/blastradius/server/static/js/d3.v4.js similarity index 100% rename from blastradius/server/static/js/d3.v4.js rename to bin/blastradius/server/static/js/d3.v4.js diff --git a/blastradius/server/static/js/d3.v4.min.js b/bin/blastradius/server/static/js/d3.v4.min.js similarity index 100% rename from blastradius/server/static/js/d3.v4.min.js rename to bin/blastradius/server/static/js/d3.v4.min.js diff --git a/blastradius/server/static/js/fontawesome-all.min.js b/bin/blastradius/server/static/js/fontawesome-all.min.js similarity index 100% rename from blastradius/server/static/js/fontawesome-all.min.js rename to bin/blastradius/server/static/js/fontawesome-all.min.js diff --git a/blastradius/server/static/js/jquery.slim.min.js b/bin/blastradius/server/static/js/jquery.slim.min.js similarity index 100% rename from blastradius/server/static/js/jquery.slim.min.js rename to bin/blastradius/server/static/js/jquery.slim.min.js diff --git a/blastradius/server/static/js/selectize.js b/bin/blastradius/server/static/js/selectize.js similarity index 100% rename from blastradius/server/static/js/selectize.js rename to bin/blastradius/server/static/js/selectize.js diff --git a/blastradius/server/static/js/svg-pan-zoom.js b/bin/blastradius/server/static/js/svg-pan-zoom.js similarity index 100% rename from blastradius/server/static/js/svg-pan-zoom.js rename to bin/blastradius/server/static/js/svg-pan-zoom.js diff --git a/blastradius/server/templates/error.html b/bin/blastradius/server/templates/error.html similarity index 100% rename from blastradius/server/templates/error.html rename to bin/blastradius/server/templates/error.html diff --git a/blastradius/server/templates/index.html b/bin/blastradius/server/templates/index.html similarity index 100% rename from blastradius/server/templates/index.html rename to bin/blastradius/server/templates/index.html diff --git a/blastradius/server/templates/non_tf_dir.html b/bin/blastradius/server/templates/non_tf_dir.html similarity index 100% rename from blastradius/server/templates/non_tf_dir.html rename to bin/blastradius/server/templates/non_tf_dir.html diff --git a/blastradius/util.py b/bin/blastradius/util.py similarity index 100% rename from blastradius/util.py rename to bin/blastradius/util.py diff --git a/requirements.txt b/requirements.txt index cf97139..743df34 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,11 +1,10 @@ -setuptools==63.4.3 +setuptools==65.5.1 requests==2.27.1 Jinja2==3.1.2 Flask==2.1.2 beautifulsoup4==4.11.1 ply>=3.11 -python-hcl2==3.0.1 +python-hcl2==3.0.5 markupsafe==2.0.1 pyhcl<=0.4.4 -itsdangerous==2.0.1 -# hcl<=0.2.1 \ No newline at end of file +itsdangerous==2.0.1 \ No newline at end of file diff --git a/setup.py b/setup.py deleted file mode 100644 index 03f097f..0000000 --- a/setup.py +++ /dev/null @@ -1,26 +0,0 @@ -from setuptools import setup, find_packages -from os import path - -here = path.abspath(path.dirname(__file__)) - -# Get the long description from the README file -with open(path.join(here, 'README.md'), encoding='utf-8') as f: - long_description = f.read() - -# Implements parse_requirements as standalone functionality -with open("requirements.txt") as f: - reqs = [l.strip('\n') for l in f if l.strip('\n') and not l.startswith('#')] - -setup( - name='blastradius', - version='0.1.25', - description='Interactive Terraform graph visualizations', - long_description=open('README.md').read(), - long_description_content_type='text/markdown', - author='Patrick McMurchie', - author_email='patrick.mcmurchie@gmail.com', - packages=find_packages(exclude=['ez_setup', 'examples', 'tests']), - scripts=['bin/blast-radius'], - install_requires=reqs, - include_package_data=True, -)