Skip to content

Instantly share code, notes, and snippets.

@MrEcco
Created October 23, 2020 21:46
Show Gist options
  • Save MrEcco/c9010144764e7ce62995bcaf7c30ec32 to your computer and use it in GitHub Desktop.
Save MrEcco/c9010144764e7ce62995bcaf7c30ec32 to your computer and use it in GitHub Desktop.
Little tricks for binding terraform state to current branch
# ~/.bashrc: executed by bash(1) for non-login shells.
# see /usr/share/doc/bash/examples/startup-files (in the package bash-doc)
# for examples
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
# don't put duplicate lines or lines starting with space in the history.
# See bash(1) for more options
HISTCONTROL=ignoreboth
# append to the history file, don't overwrite it
shopt -s histappend
# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
HISTSIZE=1000
HISTFILESIZE=2000
# check the window size after each command and, if necessary,
# update the values of LINES and COLUMNS.
shopt -s checkwinsize
# If set, the pattern "**" used in a pathname expansion context will
# match all files and zero or more directories and subdirectories.
#shopt -s globstar
# make less more friendly for non-text input files, see lesspipe(1)
[ -x /usr/bin/lesspipe ] && eval "$(SHELL=/bin/sh lesspipe)"
# set variable identifying the chroot you work in (used in the prompt below)
if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
debian_chroot=$(cat /etc/debian_chroot)
fi
# set a fancy prompt (non-color, unless we know we "want" color)
case "$TERM" in
xterm-color|*-256color) color_prompt=yes;;
esac
# uncomment for a colored prompt, if the terminal has the capability; turned
# off by default to not distract the user: the focus in a terminal window
# should be on the output of commands, not on the prompt
force_color_prompt=yes
if [ -n "$force_color_prompt" ]; then
if [ -x /usr/bin/tput ] && tput setaf 1 >&/dev/null; then
# We have color support; assume it's compliant with Ecma-48
# (ISO/IEC-6429). (Lack of such support is extremely rare, and such
# a case would tend to support setf rather than setaf.)
color_prompt=yes
else
color_prompt=
fi
fi
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u@\h:\w\$ '
fi
unset color_prompt force_color_prompt
# If this is an xterm set the title to user@host:dir
case "$TERM" in
xterm*|rxvt*)
PS1="\[\e]0;${debian_chroot:+($debian_chroot)}\u@\h: \w\a\]$PS1"
;;
*)
;;
esac
# enable color support of ls and also add handy aliases
if [ -x /usr/bin/dircolors ]; then
test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
alias ls='ls --color=auto'
#alias dir='dir --color=auto'
#alias vdir='vdir --color=auto'
alias grep='grep --color=auto'
alias fgrep='fgrep --color=auto'
alias egrep='egrep --color=auto'
fi
# colored GCC warnings and errors
#export GCC_COLORS='error=01;31:warning=01;35:note=01;36:caret=01;32:locus=01:quote=01'
# some more ls aliases
alias ll='ls -alF'
alias la='ls -A'
alias l='ls -CF'
# Add an "alert" alias for long running commands. Use like so:
# sleep 10; alert
alias alert='notify-send --urgency=low -i "$([ $? = 0 ] && echo terminal || echo error)" "$(history|tail -n1|sed -e '\''s/^\s*[0-9]\+\s*//;s/[;&|]\s*alert$//'\'')"'
# Alias definitions.
# You may want to put all your additions into a separate file like
# ~/.bash_aliases, instead of adding them here directly.
# See /usr/share/doc/bash-doc/examples in the bash-doc package.
if [ -f ~/.bash_aliases ]; then
. ~/.bash_aliases
fi
# enable programmable completion features (you don't need to enable
# this, if it's already enabled in /etc/bash.bashrc and /etc/profile
# sources /etc/bash.bashrc).
if ! shopt -oq posix; then
if [ -f /usr/share/bash-completion/bash_completion ]; then
. /usr/share/bash-completion/bash_completion
elif [ -f /etc/bash_completion ]; then
. /etc/bash_completion
fi
fi
eval "$(env-helper)"
version: '3.6'
services:
workbench:
container_name: awsome-project
image: awsome-project-iac:local
entrypoint: bash -c "eval $$(env-helper); kubectl proxy --address='0.0.0.0' --port=8001 --accept-hosts='.*'"
ports:
- "8001:8001"
stdin_open: true
volumes:
- ./data:/data
- ./.aws-gi:/root/.aws:ro
- ./.ssh:/root/.ssh:ro
- ./.gpg:/root/.gpg:ro
- ./.kube:/root/.kube
- ~/.terraform/.terraformrc:/root/.terraformrc:ro
- ./.git/HEAD:/githead:ro
stop_grace_period: 1s
# proxy:
# container_name: awsome-project-proxy
# image: awsome-project-iac:local
# entrypoint: bash -c "eval $$(env-helper); kubectl port-forward --address='0.0.0.0' -n smth svc/smth 8080:8080"
# ports:
# - "8080:8080"
# stdin_open: true
# volumes:
# - ./data:/data:ro
# - ./.aws-gi:/root/.aws:ro
# - ./.kube:/root/.kube:ro
# - ./.git/HEAD:/githead:ro
# stop_grace_period: 1s
FROM ubuntu:bionic
# kube{ctl,adm,let} latest: see https://storage.googleapis.com/kubernetes-release/release/stable.txt
ARG AWSCLI_VERSION=1.18.161
ARG HELM_VERSION=2.16.12
ARG KUBECTL_VERSION=1.15.3
ARG TERRAFORM_VERSION=0.13.4
ARG PACKER_VERSION=1.6.4
ARG KUBELESS_VERSION=1.0.7
ARG VAULT_VERSION=1.5.4
RUN apt-get update && \
apt-get install --no-install-recommends -y \
software-properties-common && \
add-apt-repository ppa:ansible/ansible -y && \
apt-get install --no-install-recommends -y ansible make \
curl dnsutils git jq net-tools ssh telnet zip unzip \
vim nano wget python3-pip groff bash-completion less && \
git clone https://github.com/dysosmus/ansible-completion ansible-completion && \
mv ansible-completion/ansible-*.bash /etc/bash_completion.d/ && \
apt-get clean && \
apt-get autoclean && \
apt-get autoremove && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Terraform
RUN wget -O terraform.zip https://releases.hashicorp.com/terraform/${TERRAFORM_VERSION}/terraform_${TERRAFORM_VERSION}_linux_amd64.zip && \
unzip terraform.zip && \
mv terraform /usr/local/bin/terraform && \
chmod +x /usr/local/bin/terraform && \
rm terraform.zip && \
echo "complete -C /usr/local/bin/terraform terraform" > /etc/bash_completion.d/terraform.bash && \
mv /usr/local/bin/terraform /usr/local/bin/terraform-origin
# Packer
RUN wget -O packer.zip https://releases.hashicorp.com/packer/${PACKER_VERSION}/packer_${PACKER_VERSION}_linux_amd64.zip && \
unzip packer.zip && \
mv packer /usr/local/bin/packer && \
chmod +x /usr/local/bin/packer && \
rm packer.zip && \
echo "complete -C /usr/local/bin/packer packer" > /etc/bash_completion.d/packer.bash
# Helm
RUN wget -O helm.tar.gz https://storage.googleapis.com/kubernetes-helm/helm-v${HELM_VERSION}-linux-amd64.tar.gz && \
tar xfz helm.tar.gz && \
mv linux-amd64/helm /usr/local/bin/helm && \
chmod +x /usr/local/bin/helm && \
rm -Rf linux-amd64 && \
rm helm.tar.gz && \
helm completion bash >> /etc/bash_completion.d/helm.bash
# Kubectl
RUN wget https://storage.googleapis.com/kubernetes-release/release/v${KUBECTL_VERSION}/bin/linux/amd64/kubectl -O /usr/local/bin/kubectl && \
chmod +x /usr/local/bin/kubectl && \
kubectl completion bash \
>> /etc/bash_completion.d/kubectl.bash && \
curl -sL https://raw.githubusercontent.com/kvaps/kubectl-node-shell/156053f8bd3ac7a70d59564ac486d522f252e9c7/kubectl-node_shell \
-o /usr/local/bin/kubectl-node_shell && \
chmod +x /usr/local/bin/kubectl-node_shell
# Kubeless
RUN wget https://github.com/kubeless/kubeless/releases/download/v${KUBELESS_VERSION}/kubeless_linux-amd64.zip -O kubeless.zip && \
TMPDIRNAME=$(openssl rand -hex 20) && \
mkdir ${TMPDIRNAME} && \
cd ${TMPDIRNAME} && \
unzip ../kubeless.zip && \
rm ../kubeless.zip && \
mv $(find . -type f | egrep "/kubeless$" | head -1) /usr/local/bin/kubeless && \
chmod +x /usr/local/bin/kubeless && \
cd .. && \
rm -r ${TMPDIRNAME} && \
kubeless completion bash > /etc/bash_completion.d/kubeless.bash
# Pip3
RUN pip3 --no-cache --no-cache-dir install \
setuptools \
wheel && \
pip3 --no-cache --no-cache-dir install \
configparser \
yq && \
pip3 --no-cache --no-cache-dir install \
awscli==${AWSCLI_VERSION} && \
echo "complete -C $(which aws_completer) aws" > /etc/bash_completion.d/awscli.bash
# Vault
RUN curl -o vault.zip https://releases.hashicorp.com/vault/${VAULT_VERSION}/vault_${VAULT_VERSION}_linux_amd64.zip && \
unzip vault.zip && \
rm vault.zip && \
mv vault /bin/vault && \
echo "complete -C /bin/vault vault" > /etc/bash_completion.d/hashicorp_vault.bash
COPY ./docker /docker
# Others
RUN mkdir -p /root/.kube && \
touch /root/.kube/config && \
cp /etc/skel/.profile /root/.profile && \
cp /docker/.bashrc /root/.bashrc && \
chmod +x /docker/bin/* && \
cp /docker/bin/* /usr/local/bin/
WORKDIR /data
#!/usr/bin/python3 -u
import sys, os
import configparser
# Helpers
__warn_color_in = '\033[1;97;41m'
__warn_color_wipe = '\033[0;39;49m'
def fixpath(filename):
filename = filename.strip(' ')
if filename.find('~') == 0:
filename = '{}{}'.format(
os.environ.get('HOME', '/'),
filename[1:],
)
return filename
# Instructions builers. Unsafe for envname, but must receive legal
# environment fullname ("production" or "development" at this time).
# Aliases and must be resolved by envrouter (see below).
def common(envname, envshort):
return [
'export ENV={}'.format(envname),
'export ENVSHORT={}'.format(envshort),
]
def aws(envname, envshort):
__const_awsconfig_file = fixpath('~/.aws/config')
__const_awscreds_file = fixpath('~/.aws/credentials')
__const_aws_default_profile = 'default'
configmap = {}
profile = ''
# Config
config = configparser.ConfigParser()
config.read(__const_awsconfig_file)
if __const_aws_default_profile in config.sections():
profile = __const_aws_default_profile
else:
profile = config.sections()[0] # first available
configmap.update(config[profile])
del config
# Credentials
config = configparser.ConfigParser()
config.read(__const_awscreds_file)
configmap.update(config[profile])
del config
if envname == 'development':
configmap['region'] = 'eu-west-1'
else:
configmap['region'] = 'us-east-1'
return [
'export AWS_ACCESS_KEY_ID={}'.format(configmap['aws_access_key_id']),
'export AWS_SECRET_ACCESS_KEY={}'.format(configmap['aws_secret_access_key']),
'export AWS_DEFAULT_REGION={}'.format(configmap['region']),
'export AWS_PROFILE={}'.format(profile),
]
def terraform(envname, envshort):
configmap = {
'env': envname,
'envfile': 'envs/{}.tf'.format(envname),
}
return ['export TF_VAR_{}={}'.format(k,v) for (k,v) in configmap.items()]
def kubernetes(envname, envshort):
exports = [
'export KUBECONFIG={}'.format(fixpath('~/.kube/' + envname)),
]
return exports
def getbranchname():
__git_head_filepath = '/githead' # IMPORTANT HERE
ret = ''
with open(__git_head_filepath, 'r') as fd:
for line in fd.readlines():
line = line.strip(" \n")
if line[:5] == 'ref: ':
refparts = line[5:].split('/')
if len(refparts) >= 3:
if '/'.join(refparts[0:2]) == 'refs/heads':
ret = '/'.join(refparts[2:])
return ret
def envrouter():
__branch_production = ['master']
__branch_development = ['develop']
try:
branchname = getbranchname()
except Exception as e:
print(__warn_color_in + str(e) + __warn_color_wipe, file=sys.stderr, flush=True)
return 'unspecified'
if branchname in __branch_production:
return 'production', 'prod'
elif branchname in __branch_development:
return 'development', 'dev'
else:
return 'unspecified', 'unspecified'
builders = [
aws,
terraform,
kubernetes,
common,
]
if __name__ == "__main__":
envname, envshort = envrouter()
if envname == 'unspecified': # This I see if something goes wronk - when shell into container
print(__warn_color_in + '############################################################' + __warn_color_wipe, file=sys.stderr, flush=True)
print(__warn_color_in + '### Cannot detect environment. Fallback to "unspecified" ###' + __warn_color_wipe, file=sys.stderr, flush=True)
print(__warn_color_in + '### environment. It can broke any appliements or bring ###' + __warn_color_wipe, file=sys.stderr, flush=True)
print(__warn_color_in + '### you to disruption! ###' + __warn_color_wipe, file=sys.stderr, flush=True)
print(__warn_color_in + '############################################################' + __warn_color_wipe, file=sys.stderr, flush=True)
sys.exit(128)
instructions = []
for builder in builders:
instructions = instructions + builder(envname, envshort)
print(
"\n".join(instructions),
)
#!/usr/bin/python3 -u
import sys, os, subprocess
import pathlib
__origin_command = '/usr/local/bin/terraform-origin'
__color_in = '\033[1;95m'
__color_wipe = '\033[0;39;49m'
__dispatch_file = 'globals.tf'
if __name__ == "__main__":
# Replace symlink
lets_replace = True
must_be = 'envs/{}.tf'.format(os.environ.get('ENV', 'unspecified'))
if os.path.exists(__dispatch_file):
if pathlib.Path(__dispatch_file).is_symlink():
points_to = str(pathlib.Path(__dispatch_file).resolve())
if points_to.find(os.getcwd()) == 0:
points_to = str(points_to[len(os.getcwd()):]).lstrip('/')
if points_to == must_be:
lets_replace = False
if lets_replace:
print("{}Replaced env dispatcher symlink: {} -> {}{}".format(__color_in, __dispatch_file, must_be, __color_wipe), file=sys.stderr, flush=True)
if os.path.exists(__dispatch_file) or pathlib.Path(__dispatch_file).is_symlink():
os.remove(__dispatch_file)
os.symlink(must_be, __dispatch_file)
os.execve(__origin_command, sys.argv, os.environ)
@MrEcco
Copy link
Author

MrEcco commented Oct 23, 2020

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment