Blame tools/gen-user-data

Packit Service 509fd4
#!/usr/bin/python3
Packit Service 509fd4
Packit Service 509fd4
"""
Packit Service 509fd4
gen-user-data
Packit Service 509fd4
Packit Service 509fd4
This tool generates a cloud-config user-data file from a directory containing
Packit Service 509fd4
configuration. Its main purpose is to make it easy to include files in the
Packit Service 509fd4
user-data, which need to be encoded in base64.
Packit Service 509fd4
Packit Service 509fd4
It writes the assembled user-data to standard out.
Packit Service 509fd4
Packit Service 509fd4
The configuration directory may contain:
Packit Service 509fd4
Packit Service 509fd4
* user-data.yml -- a base user-data. Anything that exists in this file will be
Packit Service 509fd4
                   transferred as-is. Any additional configuration is appended
Packit Service 509fd4
                   to already existing configuration.
Packit Service 509fd4
Packit Service 509fd4
* files/        -- a directory containing additional files to include. The
Packit Service 509fd4
                   file's path on the target system mirrors its path relative
Packit Service 509fd4
                   to this directore (`files/etc/hosts` → `/etc/hosts`). Its
Packit Service 509fd4
                   permissions are copied over, but the owner will always be
Packit Service 509fd4
                   root:root. Empty directories are ignored.
Packit Service 509fd4
"""
Packit Service 509fd4
Packit Service 509fd4
Packit Service 509fd4
import argparse
Packit Service 509fd4
import base64
Packit Service 509fd4
import json
Packit Service 509fd4
import os
Packit Service 509fd4
import stat
Packit Service 509fd4
import sys
Packit Service 509fd4
Packit Service 509fd4
Packit Service 509fd4
def octal_mode_string(mode):
Packit Service 509fd4
    """Convert stat.st_mode to the format cloud-init expects.
Packit Service 509fd4
Packit Service 509fd4
    cloud-init's write_files plugin expects file permissions in the format
Packit Service 509fd4
    returned by python2's oct() function, for example '0644'. In python3, oct()
Packit Service 509fd4
    returns a string in the new octal notation, '0o644'.
Packit Service 509fd4
    """
Packit Service 509fd4
    return "0" + oct(stat.S_IMODE(mode))[2:]
Packit Service 509fd4
Packit Service 509fd4
Packit Service 509fd4
def main():
Packit Service 509fd4
    p = argparse.ArgumentParser(description="Generate cloud-config user-data")
Packit Service 509fd4
    p.add_argument("configdir", metavar="CONFIGDIR", help="input directory")
Packit Service 509fd4
    args = p.parse_args()
Packit Service 509fd4
Packit Service 509fd4
    write_files = []
Packit Service 509fd4
Packit Service 509fd4
    filesdir = f"{args.configdir}/files"
Packit Service 509fd4
    for directory, dirs, files in os.walk(filesdir, followlinks=True):
Packit Service 509fd4
        for name in files:
Packit Service 509fd4
            path = f"{directory}/{name}"
Packit Service 509fd4
            with open(path, "rb") as f:
Packit Service 509fd4
                content = base64.b64encode(f.read()).decode("utf-8")
Packit Service 509fd4
            write_files.append({
Packit Service 509fd4
                "path": "/" + os.path.relpath(path, filesdir),
Packit Service 509fd4
                "encoding": "b64",
Packit Service 509fd4
                "content": content,
Packit Service 509fd4
                "permissions": octal_mode_string(os.lstat(path).st_mode)
Packit Service 509fd4
            })
Packit Service 509fd4
Packit Service 509fd4
    with open(f"{args.configdir}/user-data.yml") as f:
Packit Service 509fd4
        sys.stdout.write(f.read())
Packit Service 509fd4
    sys.stdout.write("write_files: ")
Packit Service 509fd4
    json.dump(write_files, sys.stdout)
Packit Service 509fd4
    sys.stdout.write("\n")
Packit Service 509fd4
Packit Service 509fd4
Packit Service 509fd4
if __name__ == "__main__":
Packit Service 509fd4
    sys.exit(main())