https://github.com/expelledboy/smash
Change the state of the universe, from <200 lines of bash!
https://github.com/expelledboy/smash
hacktoberfest infrastructure-as-code provisioning
Last synced: about 1 month ago
JSON representation
Change the state of the universe, from <200 lines of bash!
- Host: GitHub
- URL: https://github.com/expelledboy/smash
- Owner: expelledboy
- License: apache-2.0
- Created: 2020-11-04T11:24:42.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2020-11-11T05:20:41.000Z (over 4 years ago)
- Last Synced: 2025-01-22T08:38:39.944Z (3 months ago)
- Topics: hacktoberfest, infrastructure-as-code, provisioning
- Language: Shell
- Homepage:
- Size: 1.9 MB
- Stars: 3
- Watchers: 2
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# Smash
> Change the state of the universe, from <200 lines of bash!
## Introduction
I liked `terraform`, but I wanted to be evil and use the full power of bash. 👺
Using simple scripts, determine system state and create plans to change it.
```
usage: smash [-anpst] [-o action,..]
-o Only run comma seperated list of actions.
-p Plan only; generate an execution plan. Can be approved in PR.
-a Apply only; ensure state has not changed, and execute plan.
-n Dry run; print the commands that would be executed, but do not execute them.
-s Silent operation; do not print to stdout as they are executed.
-t Output planned tests in tap format.
```Lets create a simple smash action to install your dotfiles!
```sh
# Create an action directory
mkdir -p smash/install_macecho '
#!/bin/bash# We are going to need a script to install your dotfiles
git clone https://github.com/username/dotfiles.git ~/.dotfiles
' > install.shecho '
#!/bin/bash# Another to determine if dotfiles are installed
echo "DOTFILES_INSTALLED=$(test -d ~/.dotfiles && echo true)"
' > smash/install_mac/stateecho '
#!/bin/bash# Use that context to plan what must be done to install your dotfiles
if [[ "$DOTFILES_INSTALLED" != "true" ]]; then
echo "run bash ./install.sh"
fi# You could optionally add unit tests
echo "test [[ -d ~/.dotfiles ]] || exit 1"
' > smash/install_mac/state# Make them all executablable
chmod +x ./smash/install_mac/* ./install.sh# Test your action with a dry run first.
smash -n
# Create a plan
smash -p
# Review plan
cat ./smash/engine/plan
# Apply plan
smash -a# Or dont be a Becky...
smash
``````
$ smash
==> init
$ smash/install_mac/state
DOTFILES_INSTALLED=
==> plan
$ smash/install_mac/plan
run bash ./install.sh
test [[ -d /Users/anthony/.dotfiles ]]
==> run
$ bash ./install.sh
git clone https://github.com/username/dotfiles.git /Users/anthony/.dotfiles
==> test
$ [[ -d /Users/anthony/.dotfiles ]]
==> done$ echo $? # winning
0
```And you can write these scripts in any language your heart desired!
## Installation methods
**source**
```
sudo curl -L --fail \
https://raw.githubusercontent.com/expelledboy/smash/master/smash.sh \
-o /usr/local/bin/smash
sudo chmod +x /usr/local/bin/smash
```**docker**
```
docker run --rm -it -v "${PWD}:/code" expelledboy/smash:latest -o make_target
```## Guide
- Your actions must be directories installed in `./smash/`
- A smash action needs only one file `./smash//plan`
- Actions can contribute to state in `./smash//state`
- By default all actions in `./smash/*` are run unless you use the `-o` option
- Actions prefixed with `undo_` are always ignored and must use `-o`
- State is ENV vars printed to stdout by the state script in `.env` format
- eg. `MY_VAR=useful_info`
- These environment variables will be available in all phases of smash
- There are quite afew phases of smash;
- state
- plan
- setup
- run
- test
- You can hook into `setup`, `run` and `test`
- There are also pre and post hooks eg. `pre-plan` `plan` `post-plan`
- Create a hook by printing to stdout in the plan script ` cmd args`
- You can create global util scripts in `./smash/scripts/*`
- These will be available in all phases
- You can commit `./smash/engine/*` files as part of CI/CD review process### Rollbacks
Its important understand that actions push your system towards a desired state.
Rather than supporting `undo` functionality in smash actions my feeling is it
would be preferred to create actions that achieve the opposite desired state.
You can read previous system states in the `./smash/engine/state.*` files during
planning which provides maximum flexibility.Interesting side effects which fell out of the design was toggling.
```
$ smash.sh -s -o make_target,undo_make_target && ls ./target
==> done
version$ smash.sh -s -o make_target,undo_make_target && ls ./target
==> done
ls: ./target: No such file or directory$ smash.sh -s -o make_target,undo_make_target && ls ./target
==> done
version
```# Contributions
If you want to change behavior please create a unit test in `./test.sh`.
Otherwise I welcome changes early in the development of this project!