169163334 - Abstracts terraform wrapper code

The terraform wrapper is now abstracted in to a utility class for
working with terraform. The terraform module was also updated to support
configurable keyvault servers. Logging for this new module was also
added, so the terraform output is seen on the console.
This commit is contained in:
Rob Gil 2020-01-16 12:51:20 -05:00
parent deead852b5
commit aa89505650
4 changed files with 88 additions and 39 deletions

View File

@ -4,64 +4,48 @@ import logging
import subprocess
from utils.keyvault.secrets import SecretsClient
from utils.terraform.wrapper import TFWrapper
logger = logging.getLogger(__name__)
PROCESS='terraform'
@click.group()
@click.option('--keyvault', required=True, help="Specify the keyvault to operate on")
@click.pass_context
def terraform(ctx):
pass
def terraform(ctx, keyvault):
ctx.ensure_object(dict)
ctx.obj['keyvault'] = keyvault
@click.command('plan')
@click.pass_context
def plan(ctx):
keyvault = SecretsClient(vault_url="https://cloudzero-dev-keyvault.vault.azure.net/")
# Set env variables for TF
for secret in keyvault.list_secrets():
name = 'TF_VAR_' + secret
val = keyvault.get_secret(secret)
#print(val)
os.environ[name] = val
env = os.environ.copy()
command = "{} {}".format(PROCESS, 'plan')
with subprocess.Popen(command, env=env, stdout=subprocess.PIPE, shell=True) as proc:
for line in proc.stdout:
logging.info(line.decode("utf-8") )
keyvault = SecretsClient(vault_url=ctx.obj['keyvault'])
tf = TFWrapper(keyvault)
tf.plan()
@click.command('apply')
@click.pass_context
def apply(ctx):
keyvault = SecretsClient(vault_url="https://cloudzero-dev-keyvault.vault.azure.net/")
# Set env variables for TF
for secret in keyvault.list_secrets():
name = 'TF_VAR_' + secret
val = keyvault.get_secret(secret)
#print(val)
os.environ[name] = val
env = os.environ.copy()
command = "{} {}".format(PROCESS, 'apply -auto-approve')
with subprocess.Popen(command, env=env, stdout=subprocess.PIPE, shell=True) as proc:
for line in proc.stdout:
logging.info(line.decode("utf-8") )
keyvault = SecretsClient(vault_url=ctx.obj['keyvault'])
tf = TFWrapper(keyvault)
tf.apply()
@click.command('destroy')
@click.pass_context
def destroy(ctx):
keyvault = SecretsClient(vault_url="https://cloudzero-dev-keyvault.vault.azure.net/")
# Set env variables for TF
for secret in keyvault.list_secrets():
name = 'TF_VAR_' + secret
val = keyvault.get_secret(secret)
#print(val)
os.environ[name] = val
env = os.environ.copy()
command = "{} {}".format(PROCESS, 'destroy')
with subprocess.Popen(command, env=env, stdout=subprocess.PIPE, shell=True) as proc:
for line in proc.stdout:
logging.info(line.decode("utf-8") )
keyvault = SecretsClient(vault_url=ctx.obj['keyvault'])
tf = TFWrapper(keyvault)
tf.destroy()
@click.command('init')
@click.pass_context
def init(ctx):
keyvault = SecretsClient(vault_url=ctx.obj['keyvault'])
tf = TFWrapper(keyvault)
tf.init()
terraform.add_command(plan)
terraform.add_command(apply)
terraform.add_command(destroy)
terraform.add_command(destroy)
terraform.add_command(init)

View File

@ -49,6 +49,10 @@ loggers:
level: DEBUG
handlers: [console]
propogate: yes
utils.terraform.wrapper:
level: DEBUG
handlers: [console]
propogate: yes
commands:
level: INFO
handlers: [console]

View File

@ -0,0 +1,61 @@
import os
import logging
import subprocess
logger = logging.getLogger(__name__)
class TFWrapper:
"""
Command wrapper for terraform that injects secrets
from keyvault in to environment variables which
can then be used by terraform
"""
def __init__(self, keyvault: object):
self.keyvault = keyvault
self.env = ''
self.terraform_path = 'terraform'
self._set_env()
def _set_env(self):
# Prefix variables with TF_VAR_
for secret in self.keyvault.list_secrets():
name = 'TF_VAR_' + secret
val = self.keyvault.get_secret(secret)
os.environ[name] = val
# Set the environment with new vars
self.env = os.environ.copy()
return None
def _run_tf(self, option: str):
try:
command = '{} {}'.format(self.terraform_path, option)
with subprocess.Popen(command, env=self.env, stdout=subprocess.PIPE, shell=True) as proc:
for line in proc.stdout:
logging.info(line.decode("utf-8"))
except Exception as e:
print(e)
def plan(self):
"""
terraform plan
"""
self._run_tf(option='plan')
def init(self):
"""
terraform init
"""
self._run_tf(option='init')
def apply(self):
"""
terraform apply
"""
self._run_tf(option='apply -auto-approve')
def destroy(self):
"""
terraform destroy
"""
self._run_tf(option='destroy')