Skip to content

Instantly share code, notes, and snippets.

@jjongsma
Created February 22, 2014 17:28
Show Gist options
  • Save jjongsma/9158547 to your computer and use it in GitHub Desktop.
Save jjongsma/9158547 to your computer and use it in GitHub Desktop.
Packer build wrapper for generating JSON from a more flexible YAML config syntax
#!/usr/bin/python
#
# "packer build" wrapper that sets up a consistent build environment for image building.
#
# - Use common .packer_cache directory in this root directory
# - Generate JSON templates from YAML (if exists) to allow comments and includes
import sys
import os
import subprocess
import yaml
import json
import tempfile
import code
class IncludeLoader(yaml.Loader):
def __init__(self, stream):
self._root = os.path.split(stream.name)[0]
super(IncludeLoader, self).__init__(stream)
def include(self, node):
filename = os.path.join(self._root, self.construct_scalar(node))
with open(filename, 'r') as f:
return yaml.load(f, IncludeLoader)
IncludeLoader.add_constructor('!include', IncludeLoader.include)
def build_image(path):
if path and path[-1:] == '/':
path = path[:-1]
if not os.path.exists(path):
print "[ERROR] Unable to build image %s: no templates found" % path
sys.exit(1)
name = os.path.basename(path)
yaml_template = "%s/%s.yaml" % (path, name)
json_template = "%s/%s.json" % (path, name)
remove_json = False
if os.path.exists(yaml_template):
if os.path.exists(json_template):
print "[WARNING] %s: Found both JSON and YAML templates, using YAML" % path
with open(yaml_template, 'r') as infile:
template = yaml.load(infile, IncludeLoader)
# Flatten provisioners so we can include multiple steps in each include
if 'provisioners' in template:
prov = template['provisioners']
flat = []
for p in prov:
if isinstance(p, list):
flat.extend(p)
else:
flat.append(p)
template['provisioners'] = flat
(outfile, json_template) = tempfile.mkstemp('.json', 'packer')
remove_json = True
with open(json_template, 'w') as outfile:
json.dump(template, outfile)
if os.path.exists(json_template):
cwd = os.getcwd()
packer_env = os.environ.copy()
packer_env['PACKER_CACHE_DIR'] = '%s/.packer_cache' % cwd
p = subprocess.Popen(['packer', 'build', '-force', json_template], env=packer_env)
try:
p.wait()
except KeyboardInterrupt:
p.wait()
finally:
if remove_json:
os.unlink(json_template)
else:
print "[ERROR] Unable to build image %s: no templates found" % path
sys.exit(1)
if __name__ == "__main__":
for path in sys.argv[1:]:
build_image(path)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment