diff --git a/README.rst b/README.rst index da30099..da5d08b 100644 --- a/README.rst +++ b/README.rst @@ -19,6 +19,7 @@ Requirements - Python 3.x - `pyyaml`_ + - `requests`_ - Virtualbox (obviously) - ``mkisofs`` or ``genisoimage`` command for generating iso image @@ -140,11 +141,20 @@ pass filenames to the custom config, instead of filling up permissions: '0644' filename: /path/to/local/file.txt -during processing this file, boxpy will look for ``filename`` key in the yaml -file for the ``write_files`` sections, and it will remove that key, read the -file and put its contents under ``content`` key. What is more important, that -will be done after template processing, so there will be no interference for -possible ``$`` characters. +or + +.. code:: yaml + + write_files: + - path: /opt/somefile.txt + permissions: '0644' + url: https://some.url/content + +during processing this file, boxpy will look for ``filename`` or ``url`` keys +in the yaml file for the ``write_files`` sections, and it will remove that key, +read the file and put its contents under ``content`` key. What is more +important, that will be done after template processing, so there will be no +interference for possible ``$`` characters. 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 @@ -202,3 +212,4 @@ This work is licensed under GPL-3. .. _pyyaml: https://github.com/yaml/pyyaml .. _cloud-init: https://cloudinit.readthedocs.io +.. _requests: https://docs.python-requests.org diff --git a/box.py b/box.py index 76ce1a3..ace24cb 100755 --- a/box.py +++ b/box.py @@ -14,10 +14,11 @@ import time import uuid import xml.dom.minidom +import requests import yaml -__version__ = "1.0" +__version__ = "1.2" CACHE_DIR = os.environ.get('XDG_CACHE_HOME', os.path.expanduser('~/.cache')) CLOUD_IMAGE = "ci.iso" @@ -423,27 +424,52 @@ class Config: if conf.get('write_files'): new_list = [] for file_data in conf['write_files']: + content = None fname = file_data.get('filename') - if not fname: + url = file_data.get('url') + if not any((fname, url)): new_list.append(file_data) continue - fname = os.path.expanduser(os.path.expandvars(fname)) - if not os.path.exists(fname): - LOG.warning("File '%s' doesn't exists", - file_data['filename']) - continue + if fname: + key = 'filename' + content = self._read_filename(fname) + if content is None: + LOG.warning("File '%s' doesn't exists", fname) + continue - with open(fname) as fobj: - file_data['content'] = fobj.read() - del file_data['filename'] - new_list.append(file_data) + if url: + key = 'url' + code, content = self._get_url(url) + if content is None: + LOG.warning("Getting url '%s' returns %s code", + url, code) + continue + + if content: + file_data['content'] = content + del file_data[key] + new_list.append(file_data) conf['write_files'] = new_list # 3. finally dump it again. return "#cloud-config\n" + yaml.safe_dump(conf) + def _get_url(self, url): + response = requests.get(url) + if response.status_code != 200: + return response.status_code, None + return response.status_code, response.text + + def _read_filename(self, fname): + fullpath = os.path.expanduser(os.path.expandvars(fname)) + if not os.path.exists(fullpath): + return + + with open(fname) as fobj: + return fobj.read() + def _set_ssh_key_path(self): self.ssh_key_path = self.key diff --git a/requirements.txt b/requirements.txt index 933e694..c687994 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1 +1,2 @@ pyyaml>=5.4.1 +requests>=2.26.0