make believe

A while I ago I saw this tweet by @silascutler who was using make to run docker commands.

I was intrigued so I made a (very) similar Makefile and tried it when using Docker

override TAG = $(shell basename $$PWD)
VER := latest
IMAGE_ID = $(shell eval sudo docker images -qa ${TAG} | head -n 1)

.PHONY build test buildtest deploy

build:
    sudo docker build -t ${TAG}:${VER} .

test:
    sudo docker run -d ${TAG}:${VER}

buildtest: build test

deploy:
    @echo ${IMAGE_ID}
    sudo docker tag ${IMAGE_ID} pyratebeard/${TAG}:${VER}
    sudo docker push pyratebeard/${TAG}:${VER}

This Makefile will use the directory name as the container tag if not specified. I did it that way so I can have one Makefile and symlink it into every project directory. The version is set to “latest” unless declared with the command

make build VER=1.0

The rest is pretty straight forward. A new container built from the current directory can be created and started if you incant

make build
make test

Or you can perform both actions at the same time by incanting

make buildtest

Pushing your image to your remote repo is as easy as

make deploy

earth shaping in the cloud

After using this for a while I thought it was working well so I decided to try it with a few other tools.

I wrote this Makefile for use with terraform

NAME := test
VARS := terraform

.PHONY init plan apply planapply refresh destroy clean

init:
    terraform init

plan: init
    terraform plan -var-file=${VARS}.tfvars -out ${NAME}.tfplan

apply:
    terraform apply -auto-approve -state-out=${NAME}.tfstate ${NAME}.tfplan

planapply: init plan apply

refresh:
    terraform refresh -state=${NAME}.tfstate

destroy: refresh
    terraform destroy -var-file=${VARS}.tfvars -state=${NAME}.tfstate

clean: destroy
    rm -f ${NAME}.tf{plan,state{,.backup}}

Using this Makefile I can init, plan, and apply a terraform state with one command. I can also manage multiple plans in the same directory.

To create a “test” plan you incant

make plan

This will produce test.tfplan. You can then apply this plan by incanting

make apply

If you then wanted to use the same variables file (terraform.tfvars) to create another plan and apply it without losing test.tfplan you can incant

make planapply NAME=newtest

Coming back later you can destroy everything from newtest.tfplan if you incant

make destroy NAME=newtest

This will leave the newplan.tfstate file if you wanted to re-apply, or use make clean to delete everything.

as you drist

Then I got more adventurous and decided to write a Makefile for use with my drist modules (if you’re not sure what drist is you can read my post about it)

SERVER := inventory
FILESDIR = files

.PHONY patch pkgs create_user ssh_keys new_server sshd_config fail2ban dots secure commission

env-%:
        cd $* ; if [ ! -d ${FILESDIR} ] ; then mkdir ${FILESDIR} ; fi
        cp env $*/${FILESDIR}

patch:
        cd patch ; drist ${SERVER}

pkgs:
        cd packages ; drist ${SERVER}

create_user: env-create_user
        cd create_user ; drist ${SERVER}

ssh_keys:
        cd ssh_keys ; drist ${SERVER}

new_server: env-ssh_keys
        cd create_user ; drist ${SERVER}
        cd ssh_keys ; drist ${SERVER}

sshd_config: env-sshd_config
        cd sshd_config ; drist ${SERVER}

fail2ban:
        cd fail2ban ; drist ${SERVER}

dots:
        cd deploy_dots ; drist ${SERVER}

secure: sshd_config fail2ban

commission: new_server patch pkgs secure dots

There seems like a lot there but it should be fairly easy to figure out. I normally run this when I have built a new server and want to “commission” it with my settings

make commission SERVER=newhost

This will create a user and upload my ssh public keys, update the system (patch) and install a set of packages which I always want to have. It will then set a preconfigured sshd config file, install and configure fail2ban, and deploy my user configurations (dotfiles).

meet the maker

Using make like this will probably make a lot of people shudder. I don’t use it for everything but after trying the above I found writing a simple Makefile was slightly quicker than writing a wrapper script, and it’s another way for me to confuse coworkers that like buttons over text.

If you like this idea I would be interested to see what other tools people use Makefiles for. If you think the above can be improved let me know or raise a Gitlab merge request.