Skip to content

Commit ed46e02

Browse files
author
Ben Fortuna
committed
Support blueprint configuration export
1 parent a6335c5 commit ed46e02

2 files changed

Lines changed: 119 additions & 1 deletion

File tree

bedrock/cli.py

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from .backend import BackendSpec
1010
from .config import ConfigSpec
1111
from .blueprint import BlueprintSpec
12+
from .export import ExportSpec
1213
from .utils import read_blueprints, ANSIColors
1314

1415

@@ -22,6 +23,7 @@ def __init__(self):
2223
{ANSIColors.BOLD}blueprint{ANSIColors.ENDC} - configure available blueprints
2324
{ANSIColors.BOLD}config{ANSIColors.ENDC} - configure instance variable overrides
2425
destroy
26+
{ANSIColors.BOLD}export{ANSIColors.ENDC} - export blueprint configuration
2527
graph
2628
import
2729
init
@@ -45,7 +47,7 @@ def __init__(self):
4547
parser.add_argument('-q', '--quiet', action='store_true', help='suppress execution output to stdout')
4648
parser.add_argument('-var-file', metavar='<var_file>', help='override default config')
4749
parser.add_argument('command', help='Subcommand to run', choices=['apply', 'destroy', 'force-unlock', 'graph', 'import', 'init', 'output', 'plan', 'providers', 'refresh', 'show',
48-
'state', 'taint', 'untaint', 'version', 'workspace'] + ['blueprint', 'backend', 'config'])
50+
'state', 'taint', 'untaint', 'version', 'workspace'] + ['blueprint', 'backend', 'config', 'export'])
4951
parser.add_argument('cmd_args', metavar='<cmd_args>',
5052
help='additional arguments for sub-commands', nargs='*')
5153

@@ -73,6 +75,8 @@ def __init__(self):
7375
self.config(sys.argv[sys.argv.index(args.command) + 1:])
7476
elif args.command == 'blueprint':
7577
self.blueprint(sys.argv[sys.argv.index(args.command) + 1:])
78+
elif args.command == 'export':
79+
self.export(sys.argv[sys.argv.index(args.command) + 1:])
7680

7781
sys.exit()
7882

@@ -162,6 +166,20 @@ def blueprint(self, args):
162166

163167
spec.run()
164168

169+
def export(self, args):
170+
spec = ExportSpec(None, None, pull_image=self.pull_image, dry_run=self.dryrun, verbose=self.verbose)
171+
blueprint_home = BlueprintSpec.get_blueprint_home()
172+
blueprint = self.get_blueprint()
173+
spec.blueprint_home = blueprint_home
174+
spec.blueprint_id = blueprint[0]
175+
spec.image = blueprint[1]['image']
176+
spec.image_registry = BlueprintSpec.get_blueprint_registry()
177+
spec.image_tag = BlueprintSpec.get_blueprint_tag()
178+
179+
spec.instance_name = 'tf_export'
180+
181+
spec.run()
182+
165183

166184
if __name__ == "__main__":
167185
BedrockCli()

bedrock/export.py

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
1+
#!/usr/bin/env python3
2+
3+
"""
4+
Export Terraform blueprints to the local filesystem.
5+
"""
6+
import docker
7+
import docker.errors
8+
import dockerpty
9+
from .utils import *
10+
11+
12+
class ExportSpec:
13+
14+
def __init__(self, blueprint_id, instance_name, pull_image=False, dry_run=False, verbose=False):
15+
# Docker image
16+
self.image = 'hashicorp/terraform'
17+
self.image_tag = None
18+
self.image_registry = None
19+
20+
# Pull image prior to run
21+
self.pull_image = pull_image
22+
23+
# Enable dry run (skip container creation)
24+
self.dry_run = dry_run
25+
26+
# Enable verbose logging
27+
self.verbose = verbose
28+
29+
# Blueprint home directory
30+
self.blueprint_home = '.'
31+
32+
# Blueprint identifier
33+
self.blueprint_id = blueprint_id
34+
35+
# Name of blueprint instance
36+
self.instance_name = instance_name
37+
38+
def run(self):
39+
40+
if self.dry_run:
41+
print("Dry run enabled. No changes will be made.")
42+
43+
# Configure variables..
44+
workspace = current_workspace(self.blueprint_id, self.blueprint_home)
45+
46+
run_command = ["cp","-R","/blueprint/.","/work"]
47+
48+
# Initialise working directory
49+
if self.verbose:
50+
print(f"Initialising current workspace: {workspace}\n")
51+
52+
init_config(self.blueprint_id, self.blueprint_home, workspace)
53+
54+
# Configure container volumes..
55+
volumes = {
56+
os.path.expanduser(f'{self.blueprint_home}/{self.blueprint_id}'): {
57+
'bind': '/work',
58+
'mode': 'rw'
59+
},
60+
}
61+
62+
# Run container..
63+
if not self.dry_run:
64+
container = None
65+
try:
66+
print("Initialising Docker..")
67+
68+
client = docker.from_env()
69+
70+
if self.image_registry is not None:
71+
image_ref = self.image_registry + "/" + self.image
72+
else:
73+
image_ref = self.image
74+
75+
if self.pull_image:
76+
client.api.pull(image_ref, self.image_tag)
77+
78+
if self.image_tag is not None:
79+
image_ref += ":" + self.image_tag
80+
81+
print(f"Running export command: {run_command}")
82+
83+
if self.verbose:
84+
print(f"Creating container from image: {image_ref}\n")
85+
86+
container = client.api.create_container(image_ref, run_command, self.instance_name,
87+
entrypoint=[],
88+
working_dir='/work',
89+
host_config=client.api.create_host_config(binds=volumes,
90+
network_mode='host'),
91+
stdin_open=True, tty=True)
92+
93+
dockerpty.start(client.api, container)
94+
95+
except KeyboardInterrupt:
96+
print(f"Aborting {self.blueprint_id}..")
97+
if container is not None:
98+
container.stop()
99+
except docker.errors.ImageNotFound:
100+
print(f"Blueprint image not found {image_ref}.. did you run with --pull option?")

0 commit comments

Comments
 (0)