Skip to content

Instantly share code, notes, and snippets.

@bgilbert
Last active December 7, 2021 06:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bgilbert/6480e278d4fbc1aee769f8f567358c97 to your computer and use it in GitHub Desktop.
Save bgilbert/6480e278d4fbc1aee769f8f567358c97 to your computer and use it in GitHub Desktop.
Debug tool for unwrapping data URLs in Ignition configs
#!/usr/bin/python
import gzip
import json
import sys
from urllib.request import urlopen
import yaml
class literal(str):
pass
def literal_representer(dumper, data):
return dumper.represent_scalar(u'tag:yaml.org,2002:str', data, style='|')
yaml.add_representer(literal, literal_representer)
def inline(resource):
if not resource.get('source', '').startswith('data:'):
return False
with urlopen(resource['source']) as resp:
data = resp.read()
del resource['source']
if resource.get('compression') == 'gzip':
del resource['compression']
data = gzip.decompress(data)
try:
data = data.decode()
except UnicodeError:
pass
resource['inline'] = literal(data)
return True
def convert(data):
conf = json.loads(data)
for item in conf.get('ignition', {}).get('config', {}).get('merge', []):
if inline(item):
item['inline'] = convert(item['inline'])
for item in conf.get('ignition', {}).get('security', {}).get('tls', {}).get('certificateAuthorities', []):
inline(item)
for file in conf.get('storage', {}).get('files', []):
contents = file.get('contents', {})
if inline(contents) and file['path'].endswith('.ign'):
contents['inline'] = convert(contents['inline'])
for unit in conf.get('systemd', {}).get('units', []):
contents = unit.get('contents')
if contents:
unit['contents'] = literal(contents)
return literal(yaml.dump(conf))
if __name__ == '__main__':
if len(sys.argv) > 1:
with open(sys.argv[1]) as fh:
data = fh.read()
else:
data = sys.stdin.read()
print(convert(data), end='')
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment