From f741591d203f59faf6e041cbc6b6974ad2246144 Mon Sep 17 00:00:00 2001 From: "Chris West (Faux)" Date: Thu, 1 Oct 2015 20:31:42 +0100 Subject: initial commit --- README.md | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ ghetto_json | 53 +++++++++++++++++++++++++++++++++++++++++ test.sh | 8 +++++++ 3 files changed, 140 insertions(+) create mode 100644 README.md create mode 100755 ghetto_json create mode 100755 test.sh diff --git a/README.md b/README.md new file mode 100644 index 0000000..a37640f --- /dev/null +++ b/README.md @@ -0,0 +1,79 @@ +ghetto_json +=========== + +Need a quick way to edit a JSON file in Ansible? Ansible has great built-in support for + ini files, but a number of more modern applications are using JSON for config files. + +ghetto_json lets you make some types of edits to JSON files, and remains simple enough that + it's hopefully easier just to extend than to switch to a different module, and you won't feel + too guilty just copy-pasting it into your codebase. + + +Installation +------------ + +Drop ``ghetto_json`` into your playbook's ``library`` folder, + which can be [configured](https://docs.ansible.com/ansible/intro_configuration.html#library) + but defaults to ``./library`` inside a playbook. + +Synopsis +-------- + +Make in-place changes to simple JSON documents, + without having to resort to ``replace``. + + +Requirements +------------ + +Python 2.7 may be required for some ``shlex`` functionality + (like working Unicode), which you probably don't care about. + + +Options +------- + +#### path: + +The file on the target to edit. + +#### all other options: + +A very simple object notation for the location of the property to edit, + and its new value. + +Mandatory automatic conversion will be applied. Supported values: + + * integers (``5``, ``-17``) + * ``true`` / ``false`` + * ``null`` + * ``unset`` will delete the key + + +Examples +-------- + +For the example JSON document ``/foo/bar.json`` containing: +```` +{ "a": 5, "b": {"c": 6, "d": "hello" } } +```` + +...you can run an invocation like: +```` + - ghetto_json: + path=/foo/bar.json + a=7 + b.c=yellow + b.d=unset +```` + +...and the file will be left looking like: + +```` +{ + "a": 7, + "b": { + "c": "yellow" + } +} +```` diff --git a/ghetto_json b/ghetto_json new file mode 100755 index 0000000..075accb --- /dev/null +++ b/ghetto_json @@ -0,0 +1,53 @@ +#!/usr/bin/env python + +import json +import sys +import shlex + + +def main(params_list): + params = dict(x.split("=", 2) for x in params_list) + path = params.pop('path') + changed = False + + with open(path) as f: + obj = json.load(f) + for (key, target) in params.items(): + parts = key.split('.') + ref = obj + for part in parts[:-1]: + if part not in ref: + ref[part] = {} + ref = ref[part] + + last_part = parts[-1] + if target == 'unset': + if last_part in ref: + del ref[last_part] + changed = True + else: + if target.isdigit(): + target = int(target) + if target == 'null': + target = None + if target == 'false': + target = False + if target == 'true': + target = True + if last_part not in ref or ref[last_part] != target: + ref[last_part] = target + changed = True + + if changed: + with open(path, 'w') as f: + json.dump(obj, f, indent=2, separators=(',', ': '), sort_keys=True) + + print(json.dumps({'changed': changed})) + + +if __name__ == '__main__': + if len(sys.argv) == 2: + main(shlex.split(open(sys.argv[1]).read())) + else: + main(sys.argv[1:]) + diff --git a/test.sh b/test.sh new file mode 100755 index 0000000..76e4e12 --- /dev/null +++ b/test.sh @@ -0,0 +1,8 @@ +#!/bin/bash +set -eu +T=$(mktemp) +trap "rm $T" EXIT +echo '{ "a": 5, "b": {"c": 6, "d": "hello" } }' > $T +python ghetto_json path=$T a=7 b.c=yellow b.d=unset +diff -u <(printf '{\n "a": 7,\n "b": {\n "c": "yellow"\n }\n}') $T + -- cgit v1.2.3