mirror of
https://github.com/gryf/boxpy.git
synced 2025-12-22 07:17:59 +01:00
Process template before reading files into cloud init.
This commit is contained in:
@@ -101,6 +101,13 @@ It is really simple, and use ``string.Template`` for exchanging token
|
|||||||
log in into the VM using that key. Section ``power_state`` is used internally
|
log in into the VM using that key. Section ``power_state`` is used internally
|
||||||
for making sure the cloud-init finish up and the VM will be started again.
|
for making sure the cloud-init finish up and the VM will be started again.
|
||||||
|
|
||||||
|
Note, that you need to be extra careful regarding ``$`` sign. As explained
|
||||||
|
above ``$ssh_key`` will be used as a "variable" for the template to substitute
|
||||||
|
with the real value of public key. Every ``$`` sign, especially in
|
||||||
|
``write_files.contents``, should be escaped with another dollar, so the ``$``
|
||||||
|
will become a ``$$``. Perhaps I'll change the approach for writing ssh key,
|
||||||
|
since that's a little bit annoying.
|
||||||
|
|
||||||
What is more interesting is the fact, that you could use whatever cloud-init
|
What is more interesting is the fact, that you could use whatever cloud-init
|
||||||
accepts, and a special section, for keeping configuration, so that you don't
|
accepts, and a special section, for keeping configuration, so that you don't
|
||||||
need to provide all the option every time you boot up similar VM. For example:
|
need to provide all the option every time you boot up similar VM. For example:
|
||||||
|
|||||||
96
box.py
96
box.py
@@ -267,10 +267,56 @@ class Config:
|
|||||||
|
|
||||||
# finally, figure out host name
|
# finally, figure out host name
|
||||||
self.hostname = self.hostname or self._normalize_name()
|
self.hostname = self.hostname or self._normalize_name()
|
||||||
|
self._set_ssh_key_path()
|
||||||
|
|
||||||
def get_cloud_config_tpl(self):
|
def get_cloud_config(self):
|
||||||
conf = "#cloud-config\n" + yaml.safe_dump(self._conf)
|
# 1. process template
|
||||||
return string.Template(conf)
|
tpl = string.Template(yaml.safe_dump(self._conf))
|
||||||
|
|
||||||
|
with open(self.ssh_key_path) as fobj:
|
||||||
|
ssh_pub_key = fobj.read().strip()
|
||||||
|
|
||||||
|
conf = yaml.safe_load(tpl.substitute({'ssh_key': ssh_pub_key}))
|
||||||
|
|
||||||
|
# 2. process 'write_files' items, so that things with '$' will not go
|
||||||
|
# in a way for templates.
|
||||||
|
if conf.get('write_files'):
|
||||||
|
new_list = []
|
||||||
|
for file_data in conf['write_files']:
|
||||||
|
fname = file_data.get('filename')
|
||||||
|
if not fname:
|
||||||
|
new_list.append(file_data)
|
||||||
|
continue
|
||||||
|
|
||||||
|
fname = os.path.expanduser(os.path.expandvars(fname))
|
||||||
|
if not os.path.exists(fname):
|
||||||
|
print(f"WARNING: file '{file_data['filename']}' doesn't "
|
||||||
|
f"exists.")
|
||||||
|
continue
|
||||||
|
|
||||||
|
with open(fname) as fobj:
|
||||||
|
file_data['content'] = fobj.read()
|
||||||
|
del file_data['filename']
|
||||||
|
new_list.append(file_data)
|
||||||
|
|
||||||
|
conf['write_files'] = new_list
|
||||||
|
|
||||||
|
# 3. finally dump it again.
|
||||||
|
return "#cloud-config\n" + yaml.safe_dump(conf)
|
||||||
|
|
||||||
|
def _set_ssh_key_path(self):
|
||||||
|
self.ssh_key_path = self.key
|
||||||
|
|
||||||
|
if not self.ssh_key_path.endswith('.pub'):
|
||||||
|
self.ssh_key_path += '.pub'
|
||||||
|
if not os.path.exists(self.ssh_key_path):
|
||||||
|
self.ssh_key_path = os.path.join(os.path
|
||||||
|
.expanduser(self.ssh_key_path))
|
||||||
|
if not os.path.exists(self.ssh_key_path):
|
||||||
|
self.ssh_key_path = os.path.join(os.path.expanduser("~/.ssh"),
|
||||||
|
self.ssh_key_path)
|
||||||
|
if not os.path.exists(self.ssh_key_path):
|
||||||
|
raise BoxNotFound(f'Cannot find ssh public key: {conf.key}')
|
||||||
|
|
||||||
def _set_defaults(self):
|
def _set_defaults(self):
|
||||||
conf = yaml.safe_load(USER_DATA)
|
conf = yaml.safe_load(USER_DATA)
|
||||||
@@ -304,28 +350,6 @@ class Config:
|
|||||||
continue
|
continue
|
||||||
setattr(self, key, str(val))
|
setattr(self, key, str(val))
|
||||||
|
|
||||||
# check if there are files to be written
|
|
||||||
if conf.get('write_files'):
|
|
||||||
new_list = []
|
|
||||||
for file_data in conf['write_files']:
|
|
||||||
fname = file_data.get('filename')
|
|
||||||
if not fname:
|
|
||||||
new_list.append(file_data)
|
|
||||||
continue
|
|
||||||
|
|
||||||
fname = os.path.expanduser(os.path.expandvars(fname))
|
|
||||||
if not os.path.exists(fname):
|
|
||||||
print(f"WARNING: file '{file_data['filename']}' doesn't "
|
|
||||||
f"exists.")
|
|
||||||
continue
|
|
||||||
|
|
||||||
with open(fname) as fobj:
|
|
||||||
file_data['content'] = fobj.read()
|
|
||||||
del file_data['filename']
|
|
||||||
new_list.append(file_data)
|
|
||||||
|
|
||||||
conf['write_files'] = new_list
|
|
||||||
|
|
||||||
# remove boxpy_data since it will be not needed on the guest side
|
# remove boxpy_data since it will be not needed on the guest side
|
||||||
if conf.get('boxpy_data'):
|
if conf.get('boxpy_data'):
|
||||||
if conf['boxpy_data'].get('advanced'):
|
if conf['boxpy_data'].get('advanced'):
|
||||||
@@ -626,20 +650,7 @@ class IsoImage:
|
|||||||
def __init__(self, conf):
|
def __init__(self, conf):
|
||||||
self._tmp = tempfile.mkdtemp()
|
self._tmp = tempfile.mkdtemp()
|
||||||
self.hostname = conf.hostname
|
self.hostname = conf.hostname
|
||||||
self.ssh_key_path = conf.key
|
self._cloud_conf = conf.get_cloud_config()
|
||||||
|
|
||||||
if not self.ssh_key_path.endswith('.pub'):
|
|
||||||
self.ssh_key_path += '.pub'
|
|
||||||
if not os.path.exists(self.ssh_key_path):
|
|
||||||
self.ssh_key_path = os.path.join(os.path
|
|
||||||
.expanduser(self.ssh_key_path))
|
|
||||||
if not os.path.exists(self.ssh_key_path):
|
|
||||||
self.ssh_key_path = os.path.join(os.path.expanduser("~/.ssh"),
|
|
||||||
self.ssh_key_path)
|
|
||||||
if not os.path.exists(self.ssh_key_path):
|
|
||||||
raise BoxNotFound(f'Cannot find ssh public key: {conf.key}')
|
|
||||||
|
|
||||||
self.ud_tpl = conf.get_cloud_config_tpl()
|
|
||||||
|
|
||||||
def get_generated_image(self):
|
def get_generated_image(self):
|
||||||
self._create_cloud_image()
|
self._create_cloud_image()
|
||||||
@@ -656,11 +667,8 @@ class IsoImage:
|
|||||||
'vmhostname': self.hostname}))
|
'vmhostname': self.hostname}))
|
||||||
|
|
||||||
# user-data
|
# user-data
|
||||||
with open(self.ssh_key_path) as fobj:
|
|
||||||
ssh_pub_key = fobj.read().strip()
|
|
||||||
|
|
||||||
with open(os.path.join(self._tmp, 'user-data'), 'w') as fobj:
|
with open(os.path.join(self._tmp, 'user-data'), 'w') as fobj:
|
||||||
fobj.write(self.ud_tpl.substitute({'ssh_key': ssh_pub_key}))
|
fobj.write(self._cloud_conf)
|
||||||
|
|
||||||
mkiso = 'mkisofs' if shutil.which('mkisofs') else 'genisoimage'
|
mkiso = 'mkisofs' if shutil.which('mkisofs') else 'genisoimage'
|
||||||
|
|
||||||
@@ -736,7 +744,7 @@ def vmcreate(args, conf=None):
|
|||||||
_cleanup(vbox, iso, image, path_to_iso)
|
_cleanup(vbox, iso, image, path_to_iso)
|
||||||
vbox.poweron()
|
vbox.poweron()
|
||||||
print('You can access your VM by issuing:')
|
print('You can access your VM by issuing:')
|
||||||
print(f'ssh -p {conf.port} -i {iso.ssh_key_path[:-4]} ubuntu@localhost')
|
print(f'ssh -p {conf.port} -i {conf.ssh_key_path[:-4]} ubuntu@localhost')
|
||||||
return 0
|
return 0
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user