2019-04-09 16:54:28 +02:00
#!/usr/bin/env python3
2019-04-10 13:47:03 +02:00
import argparse , subprocess , shlex , sys , os , glob
2019-04-09 16:54:28 +02:00
def main ( argv ) :
parser = argparse . ArgumentParser ( description = ' Control Terraform Workspaces. ' )
2019-04-10 12:00:01 +02:00
g = parser . add_mutually_exclusive_group ( )
g . add_argument ( " command " , help = " Send commands to terraform with workspace variable context " , nargs = ' ? ' , default = False )
2019-04-17 11:44:14 +02:00
parser . add_argument ( " -e " , help = " Gather shared-creds from environment variables (Dont use this flag if you dont want your ~/.aws/credentials replaced. This is for CI/CD " , action = ' store_true ' , default = False )
parser . add_argument ( " -m " , help = " Prevents workspace from changing with git branches automatically " , action = ' store_true ' , default = False )
2019-07-17 09:34:14 +02:00
parser . add_argument ( " -n " , help = " Atmos will not add -var-file or -var args to terraform " , action = ' store_true ' , default = False )
2019-07-17 10:15:21 +02:00
parser . add_argument ( " -p " , " --project " , help = " Add a project prefix for env vars " , nargs = ' ? ' , default = " " )
parser . add_argument ( " -v " , " --verbose " , help = " Debug mode " , action = " store_true " , default = False )
2019-04-10 12:00:01 +02:00
args , params = parser . parse_known_args ( )
if args . command :
determine_actions ( args , params )
def determine_actions ( args , params ) :
2019-07-16 17:12:34 +02:00
aws_creds_file = " $HOME/.aws/credentials "
2019-04-17 11:44:14 +02:00
if ( is_git_directory ( ) ) and not ( args . m ) :
2019-07-17 10:15:21 +02:00
if ( args . e ) :
aws_creds_file = aws_creds_file + " -atmos "
2019-04-17 11:44:14 +02:00
workspace_manager ( )
2019-04-15 15:15:39 +02:00
workspace = get_env ( )
2019-08-01 11:01:45 +02:00
workspace_vars = workspace
if ( args . project ) :
2019-08-15 17:32:45 +02:00
workspace = args . project + " - " + workspace
2019-08-01 11:01:45 +02:00
env_actions = [ " init " , " plan " , " apply " , " destroy " ] # Commands that require env context
2019-04-10 12:00:01 +02:00
cmd = ' terraform {args} ' . format ( args = args . command )
2019-07-17 09:34:14 +02:00
if ( args . command in env_actions ) and not ( args . n ) : # Append with env context
2019-08-01 11:01:45 +02:00
cmd = cmd + ' -var-file=vars/ {env} .tfvars ' . format ( env = workspace_vars )
cmd = cmd + ' -var " workspace= {env} " ' . format ( env = workspace )
2019-07-17 10:15:21 +02:00
cmd = cmd + ' -var " shared_credentials_file= {aws_creds_file} " ' . format ( aws_creds_file = aws_creds_file )
2019-06-12 15:55:01 +02:00
2019-04-10 12:00:01 +02:00
for param in params : # Pass terraform params directly through
cmd = cmd + ' ' + param
2019-04-17 10:59:30 +02:00
if ( args . e ) :
2019-07-17 10:15:21 +02:00
generate_creds ( args )
if ( args . verbose ) :
print ( " Atmos will run: " + cmd )
2019-08-01 11:01:45 +02:00
print ( ' Terraform {args} using env vars in {env} ' . format ( args = args . command , env = workspace_vars ) )
2019-04-10 12:00:01 +02:00
with subprocess . Popen ( shlex . split ( cmd ) ) as proc :
exit # Start process but kill py program
2019-04-17 10:53:05 +02:00
def is_git_directory ( path = ' . ' ) :
2019-04-17 11:44:14 +02:00
return subprocess . call ( [ ' git ' , ' -C ' , path , ' status ' ] , stderr = subprocess . STDOUT , stdout = open ( os . devnull , ' w ' ) ) == 0
def workspace_manager ( ) :
branch = subprocess . getoutput ( " git rev-parse --abbrev-ref HEAD " )
if branch == " master " :
branch = " default "
2019-04-17 10:53:05 +02:00
else :
2019-04-17 11:44:14 +02:00
if branch not in get_valid_envs ( ) :
branch = " qa "
if get_env ( ) != branch :
print ( " [INFO]: Terraform workspace & git branch have diverged. Changing workspace to git branch... " )
subprocess . call ( [ " terraform " , " workspace " , " new " , branch ] , stderr = subprocess . STDOUT , stdout = open ( os . devnull , ' w ' ) )
subprocess . call ( [ " terraform " , " workspace " , " select " , branch ] , stderr = subprocess . STDOUT , stdout = open ( os . devnull , ' w ' ) )
2019-04-17 10:53:05 +02:00
2019-07-17 10:15:21 +02:00
def generate_creds ( args ) :
2019-04-15 15:15:39 +02:00
current_workspace = get_env ( )
workspaces = [ ' default ' ]
if current_workspace != ' default ' :
workspaces . append ( current_workspace )
2019-07-17 10:15:21 +02:00
project_name = " "
if ( args . project ) :
2019-08-15 17:32:45 +02:00
project_name = args . project . upper ( ) + " - "
2019-07-17 10:15:21 +02:00
2019-04-15 15:15:39 +02:00
contents = " "
for workspace in workspaces :
2019-07-17 10:15:21 +02:00
access_key_name = project_name + workspace . upper ( ) + ' _ACCESS_KEY_ID '
secret_key_name = project_name + workspace . upper ( ) + ' _SECRET_ACCESS_KEY '
if ( args . verbose ) :
print ( access_key_name )
print ( secret_key_name )
2019-08-15 17:32:45 +02:00
contents = contents + " [ {workspace} ] \n " . format ( workspace = project_name + workspace )
2019-07-29 15:01:15 +02:00
try :
contents = contents + " aws_access_key_id= " + os . environ . get ( access_key_name ) + " \n "
except :
print ( " [ERROR]: Env Variable " + access_key_name + " not found. " )
sys . exit ( 1 )
try :
contents = contents + " aws_secret_access_key= " + os . environ . get ( secret_key_name ) + " \n "
except :
print ( " [ERROR]: Env Variable " + secret_key_name + " not found. " )
sys . exit ( 1 )
2019-07-16 17:12:34 +02:00
with open ( os . path . expanduser ( ' ~/.aws/credentials-atmos ' ) , ' w+ ' ) as f :
2019-04-15 15:15:39 +02:00
f . write ( contents )
2019-04-10 12:00:01 +02:00
def get_valid_envs ( ) :
try :
2019-04-10 13:47:03 +02:00
# Use var files when present, otherwise default to qa
return [ os . path . splitext ( os . path . basename ( x ) ) [ 0 ] for x in glob . glob ( " vars/*.tfvars " ) ]
2019-04-10 12:00:01 +02:00
except FileNotFoundError :
return False
2019-04-09 16:54:28 +02:00
def get_env ( ) :
2019-04-10 13:47:03 +02:00
try :
tf_env = open ( ' .terraform/environment ' , ' r ' ) . read ( )
except :
2019-04-15 15:15:39 +02:00
return ( " default " )
2019-04-10 12:00:01 +02:00
if str ( tf_env ) in get_valid_envs ( ) :
2019-04-09 16:54:28 +02:00
return ( tf_env )
else :
return ( " qa " )
if __name__ == " __main__ " :
main ( sys . argv )