packer.py - python library for interacting with hashicorp packer CLI executable.
Project follows semantic versioning , v0.x.x API should be considered unstable, API will change frequently, please plan accordingly.
packer.py can be installed via pip:
$ pip install packer.py
Access to hashicorp packer executable is needed in order to use packer.py. When generating commands, if no location is specified, the following defaults are used.
*nix: /usr/local/packer macOS: /usr/local/packer windows: packer.exe
These defaults can be overridden by explicitly setting the location of packer for your environment.
PackerExecutable(executable_path="/usr/local/bin/packer")
or
PackerExecutable("/usr/local/bin/packer")
Commands are executed with packer's machine readable format enabled by default. This can be disabled by setting
PackerExecutable(machine_readable=False)
The following commands are currently supported:
- build
- inspect
- validate
- version
Below is the packer.py equivalent of running these packer CLI commands
Templates are specified by passing their filepath to the command.
template = 'tests/templates/test_template1.json'
PackerExecutable().validate(template)
Templates can also be specified as a string literal.
template = """
{
"variables": {
"my_var1": "{{env `key1`}}"
},
"builders": [
{
"type": "file",
"content": "Lorem ipsum dolor sit amet {{user `my_var1`}} ",
"target": "/tmp/packer.test"
}
]
}
"""
PackerExecutable().validate(template)
packerlicious templates can also be used and combined with packer.py.
from packerlicious import builder, Template, EnvVar
from packerpy import PackerExecutable
var1 = EnvVar("my_var1")
var2 = EnvVar("my_var2")
file_builder = builder.File()
file_builder = builder.File(content="{} more words {}".format(var2.ref().data, var1.ref().data),
target="/tmp/packer.test"
)
template = Template()
template.add_variable([var1, var2])
template.add_builder(file_builder)
p = PackerExecutable("/usr/local/bin/packer")
template_vars = {'my_var1': 'my_val1', 'my_var2': 'my_val2'}
p.build(template.to_json(),
var=template_vars
)
packer CLI commands arguments can be specified by passing them as packer.py method arguments.
$ packer validate -syntax-only -var "key1=my_value" tests/templates/test_template1.json
p = PackerExecutable("/usr/local/bin/packer")
template = 'tests/templates/test_template1.json'
p.validate(template,
syntax_only=True,
var="key1=my_value"
)
The following rules are used by packer.py when converting to packer CLI commands.
If the packer command option has a dash in it, pass it to packer.py with an underscore.
-on-error=cleanup : | on_error='cleanup' |
---|
If the packer command option is either a boolean option or an option with an implicit value, pass it to packer.py as a boolean.
-color=false : | color=False |
---|---|
-force : | force=True |
If the packer command options can be specified multiple times, pass the value as a dictionary to packer.py.
Multiple -var
option is an example of this.
$ packer build -var 'my_var1=my_val1' -var 'my_var2=my_val2' tests/templates/test_template1.json
from packerpy import PackerExecutable
p = PackerExecutable("/usr/local/bin/packer")
template = 'tests/templates/test_template1.json'
template_vars = { 'my_var1': 'my_val1', 'my_var2': 'my_val2' }
p.build(template,
var=template_vars
)
$ packer build template.json
>>> from packerpy import PackerExecutable
>>> p = PackerExecutable("/usr/local/bin/packer")
>>> (ret, out, err) = p.build('tests/templates/test_template1.json')
>>> ret==0
True
>>> print(ret)
0
>>> print(out)
b"1552841678,,ui,say,Build 'file' finished.\n1552841678,,ui,say,\\n==> Builds finished. The artifacts of successful builds are:\n1552841678,file,artifact-count,1\n1552841678,file,artifact,0,builder-id,packer.file\n1552841678,file,artifact,0,id,File\n1552841678,file,artifact,0,string,Stored file: /tmp/packer.test \n1552841678,file,artifact,0,files-count,1\n1552841678,file,artifact,0,file,0,/tmp/packer.test \n1552841678,file,artifact,0,end\n1552841678,,ui,say,--> file: Stored file: /tmp/packer.test \n"
>>> print(err)
b''
Example of a failed build.
>>> from packerpy import PackerExecutable
>>> p = PackerExecutable("/usr/local/bin/packer")
>>> bad_template = """{
... "builders": [
... {
... "type": "amazon-ebs",
... "access_key": "..."
... }
... ]
... }
... """
>>> (ret, out, err) = p.build(bad_template)
>>> ret==0
False
>>> print(ret)
1
>>> print(out)
b'1552841800,,ui,error,5 error(s) occurred:\\n\\n* ami_name must be specified\\n* ami_name must be between 3 and 128 characters long\\n* An ssh_username must be specified\\n Note: some builders used to default ssh_username to "root".\\n* A source_ami or source_ami_filter must be specified\\n* An instance_type must be specified\n'
>>> print(err)
b''
$ packer inspect template.json
>>> from packerpy import PackerExecutable
>>> p = PackerExecutable("/usr/local/bin/packer")
>>> (ret, out, err) = p.inspect('tests/templates/test_template1.json')
>>> ret==0
True
>>> print(ret)
0
>>> print(out)
b"1552841499,,ui,say,Optional variables and their defaults:\\n\n1552841499,,template-variable,my_var1,{{env `key1`}},0\n1552841499,,ui,say, my_var1 = {{env `key1`}}\n1552841499,,ui,say,\n1552841499,,ui,say,Builders:\\n\n1552841499,,template-builder,file,file\n1552841499,,ui,say, file\n1552841499,,ui,say,\n1552841499,,ui,say,Provisioners:\\n\n1552841499,,ui,say, <No provisioners>\n1552841499,,ui,say,\\nNote: If your build names contain user variables or template\\nfunctions such as 'timestamp'%!(PACKER_COMMA) these are processed at build time%!(PACKER_COMMA)\\nand therefore only show in their raw form here.\n"
>>> print(err)
b''
$ packer validate template.json
>>> from packerpy import PackerExecutable
>>> p = PackerExecutable("/usr/local/bin/packer")
>>> (ret, out, err) = p.validate('tests/templates/test_template1.json')
>>> ret==0
True
>>> print(ret)
0
>>> print(out)
b'1552840497,,ui,say,Template validated successfully.\n'
>>> print(err)
b''
Example of a template which failed to validation.
>>> from packerpy import PackerExecutable
>>> p = PackerExecutable("/usr/local/bin/packer")
>>> bad_template = """{
... "builders": [
... {
... "type": "amazon-ebs",
... "access_key": "..."
... }
... ]
... }
... """
>>> (ret, out, err) = p.validate(bad_template)
>>> ret==0
False
>>> print(ret)
1
>>> print(out)
b'1552840892,,ui,error,Template validation failed. Errors are shown below.\\n\n1552840892,,ui,error,Errors validating build \'amazon-ebs\'. 5 error(s) occurred:\\n\\n* ami_name must be specified\\n* ami_name must be between 3 and 128 characters long\\n* An ssh_username must be specified\\n Note: some builders used to default ssh_username to "root".\\n* A source_ami or source_ami_filter must be specified\\n* An instance_type must be specified\n'
>>> print(err)
b''
$ packer version
>>> from packerpy import PackerExecutable
>>> p = PackerExecutable("/usr/local/bin/packer")
>>> (ret, out, err) = p.version()
>>> ret==0
True
>>> print(ret)
0
>>> print(out)
b'1552840138,,version,1.0.3\n1552840138,,version-prelease,\n1552840138,,version-commit,c0ddb4a+CHANGES\n1552840138,,ui,say,Packer v1.0.3\n1552840138,,ui,say,\\nYour version of Packer is out of date! The latest version\\nis 1.3.5. You can update by downloading from www.packer.io\n'
>>> print(err)
b''
packer.py is licensed under the Apache license 2.0. See LICENSE for the full license text.