Adding init command and support for backend terraform state files

This commit is contained in:
Austin Page 2017-08-22 15:12:13 -05:00
parent d23f85a035
commit 825fa0e54f
No known key found for this signature in database
GPG key ID: 9329FE228ABDBAAD
4 changed files with 192 additions and 12 deletions

View file

@ -122,7 +122,7 @@ class Terraform(object):
def plan(self, dir_or_plan=None, detailed_exitcode=IsFlagged, **kwargs):
"""
refert to https://www.terraform.io/docs/commands/plan.html
refer to https://www.terraform.io/docs/commands/plan.html
:param detailed_exitcode: Return a detailed exit code when the command exits.
:param dir_or_plan: relative path to plan/folder
:param kwargs: options
@ -134,6 +134,35 @@ class Terraform(object):
args = self._generate_default_args(dir_or_plan)
return self.cmd('plan', *args, **options)
def init(self, dir_or_plan=None, backend_config=None,
reconfigure=IsFlagged, force_copy=IsNotFlagged, backend=True,
**kwargs):
"""
refer to https://www.terraform.io/docs/commands/init.html
By default, this assumes you want to use backend config, and tries to
init fresh. The flags -reconfigure and -backend=true are default.
:param backend_config: a dictionary of backend config options. eg.
t = Terraform()
t.init(backend_config={'access_key': 'myaccesskey',
'secret_key': 'mysecretkey', 'bucket': 'mybucketname'})
:param reconfigure: whether or not to force reconfiguration of backend
:param force_copy: whether or not to migrate from the previous backend
settings to the new backend settings
:param backend: whether or not to use backend settings for init
:param kwargs: options
:return: ret_code, stdout, stderr
"""
options = kwargs
options['backend_config'] = backend_config
options['reconfigure'] = reconfigure
options['force_copy'] = force_copy
options['backend'] = backend
options = self._generate_default_options(options)
args = self._generate_default_args(dir_or_plan)
return self.cmd('init', *args, **options)
def generate_cmd_string(self, cmd, *args, **kwargs):
"""
for any generate_cmd_string doesn't written as public method of terraform
@ -170,13 +199,18 @@ class Terraform(object):
cmds += ['-{k}={v}'.format(k=k, v=sub_v)]
continue
# right now we assume only variables will be passed as dict
# since map type sent in string won't work, create temp var file for
# variables, and clean it up later
if type(v) is dict:
filename = self.temp_var_files.create(v)
cmds += ['-var-file={0}'.format(filename)]
continue
if 'backend-config' in k:
for bk, bv in v.items():
cmds += ['-backend-config={k}={v}'.format(k=bk, v=bv)]
continue
# since map type sent in string won't work, create temp var file for
# variables, and clean it up later
else:
filename = self.temp_var_files.create(v)
cmds += ['-var-file={0}'.format(filename)]
continue
# simple flag,
if v is IsFlagged:
@ -274,14 +308,19 @@ class Terraform(object):
:return: states file in dict type
"""
if not file_path:
file_path = self.state
working_dir = self.working_dir or ''
file_path = file_path or self.state or ''
if not file_path:
file_path = 'terraform.tfstate'
backend_path = os.path.join(file_path, '.terraform', 'terraform.tfstate')
if self.working_dir:
file_path = os.path.join(self.working_dir, file_path)
if os.path.exists(os.path.join(working_dir, backend_path)):
file_path = backend_path
else:
file_path = os.path.join(file_path, 'terraform.tfstate')
file_path = os.path.join(working_dir, file_path)
self.tfstate = Tfstate.load_file(file_path)

View file

@ -92,9 +92,13 @@ class TestTerraform(object):
""" teardown any state that was previously setup with a setup_method
call.
"""
exclude = ['test_tfstate_file',
'test_tfstate_file2',
'test_tfstate_file3']
def purge(dir, pattern):
for root, dirnames, filenames in os.walk(dir):
dirnames[:] = [d for d in dirnames if d not in exclude]
for filename in fnmatch.filter(filenames, pattern):
f = os.path.join(root, filename)
os.remove(f)
@ -103,6 +107,7 @@ class TestTerraform(object):
shutil.rmtree(d)
purge('.', '*.tfstate')
purge('.', '*.tfstate.backup')
purge('.', '*.terraform')
purge('.', FILE_PATH_WITH_SPACE_AND_SPACIAL_CHARS)
@ -166,6 +171,18 @@ class TestTerraform(object):
tf.read_state_file()
assert tf.tfstate.modules[0]['path'] == ['root']
def test_state_default(self):
cwd = os.path.join(current_path, 'test_tfstate_file2')
tf = Terraform(working_dir=cwd)
tf.read_state_file()
assert tf.tfstate.modules[0]['path'] == ['default']
def test_state_default_backend(self):
cwd = os.path.join(current_path, 'test_tfstate_file3')
tf = Terraform(working_dir=cwd)
tf.read_state_file()
assert tf.tfstate.modules[0]['path'] == ['default_backend']
def test_pre_load_state_data(self):
cwd = os.path.join(current_path, 'test_tfstate_file')
tf = Terraform(working_dir=cwd, state='tfstate.test')

View file

@ -0,0 +1,62 @@
{
"version": 3,
"terraform_version": "0.7.10",
"serial": 0,
"lineage": "d03ecdf7-8be0-4593-a952-1d8127875119",
"modules": [
{
"path": [
"default"
],
"outputs": {},
"resources": {
"aws_instance.ubuntu-1404": {
"type": "aws_instance",
"depends_on": [],
"primary": {
"id": "i-84d10edb",
"attributes": {
"ami": "ami-9abea4fb",
"associate_public_ip_address": "true",
"availability_zone": "us-west-2b",
"disable_api_termination": "false",
"ebs_block_device.#": "0",
"ebs_optimized": "false",
"ephemeral_block_device.#": "0",
"iam_instance_profile": "",
"id": "i-84d10edb",
"instance_state": "running",
"instance_type": "t2.micro",
"key_name": "",
"monitoring": "false",
"network_interface_id": "eni-46544f07",
"private_dns": "ip-172-31-25-244.us-west-2.compute.internal",
"private_ip": "172.31.25.244",
"public_dns": "ec2-35-162-30-219.us-west-2.compute.amazonaws.com",
"public_ip": "35.162.30.219",
"root_block_device.#": "1",
"root_block_device.0.delete_on_termination": "true",
"root_block_device.0.iops": "100",
"root_block_device.0.volume_size": "8",
"root_block_device.0.volume_type": "gp2",
"security_groups.#": "0",
"source_dest_check": "true",
"subnet_id": "subnet-d2c0f0a6",
"tags.%": "0",
"tenancy": "default",
"vpc_security_group_ids.#": "1",
"vpc_security_group_ids.619359045": "sg-9fc7dcfd"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": ""
}
},
"depends_on": []
}
]
}

View file

@ -0,0 +1,62 @@
{
"version": 3,
"terraform_version": "0.7.10",
"serial": 0,
"lineage": "d03ecdf7-8be0-4593-a952-1d8127875119",
"modules": [
{
"path": [
"default_backend"
],
"outputs": {},
"resources": {
"aws_instance.ubuntu-1404": {
"type": "aws_instance",
"depends_on": [],
"primary": {
"id": "i-84d10edb",
"attributes": {
"ami": "ami-9abea4fb",
"associate_public_ip_address": "true",
"availability_zone": "us-west-2b",
"disable_api_termination": "false",
"ebs_block_device.#": "0",
"ebs_optimized": "false",
"ephemeral_block_device.#": "0",
"iam_instance_profile": "",
"id": "i-84d10edb",
"instance_state": "running",
"instance_type": "t2.micro",
"key_name": "",
"monitoring": "false",
"network_interface_id": "eni-46544f07",
"private_dns": "ip-172-31-25-244.us-west-2.compute.internal",
"private_ip": "172.31.25.244",
"public_dns": "ec2-35-162-30-219.us-west-2.compute.amazonaws.com",
"public_ip": "35.162.30.219",
"root_block_device.#": "1",
"root_block_device.0.delete_on_termination": "true",
"root_block_device.0.iops": "100",
"root_block_device.0.volume_size": "8",
"root_block_device.0.volume_type": "gp2",
"security_groups.#": "0",
"source_dest_check": "true",
"subnet_id": "subnet-d2c0f0a6",
"tags.%": "0",
"tenancy": "default",
"vpc_security_group_ids.#": "1",
"vpc_security_group_ids.619359045": "sg-9fc7dcfd"
},
"meta": {
"schema_version": "1"
},
"tainted": false
},
"deposed": [],
"provider": ""
}
},
"depends_on": []
}
]
}