Created
January 17, 2017 07:23
-
-
Save zanglang/ddfd7decc1331dcbcc59a2c0cb0d4ce2 to your computer and use it in GitHub Desktop.
Ansible module that takes in a target Java .properties file, and patches in any arbitrary key-value properties specified in a JSON hash format
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/local/python/bin/python | |
""" | |
Ansible module that takes in a target Java .properties file, and patches in any | |
arbitrary key-value properties specified in a JSON hash format. This module is | |
expected to be used alongside the `properties` Ansible action module. | |
Examples: | |
- properties: | |
dest: ~/dists/cluster/ix/ZookeeperIndexMerger.properties | |
props: | |
helloStr: Hello world! | |
@author: Jerry Chong <jchong@netbase.com> | |
@tags: WANT_JSON | |
""" | |
from __future__ import print_function | |
import json | |
import os | |
import re | |
import sys | |
from six import StringIO | |
def decode(path): | |
"""Load a JSON file from the given path""" | |
jsonfile = open(path) | |
return json.load(jsonfile) | |
def process(target, properties): | |
""" | |
Performs simple string replacements to generate a new .properties file at | |
the `target` path, using the `properties` key-value mapping | |
""" | |
# shallow copy since we will need to modify this dict later | |
src_dict = properties.copy() | |
buffer = StringIO() | |
keys = src_dict.keys() | |
prop_re = re.compile(r"^(?P<comment>#*\s*)(?P<key>[\w.]+)\s*=\s*(?P<val>.*?)?;?\s*$") | |
with open(target, "r+") as propfile: | |
for line in propfile.readlines(): | |
line = line.strip() | |
match = prop_re.match(line) | |
# if line does have key=value pattern, otherwise simply write it | |
if match: | |
commented, key, val = match.groups(default='') | |
# replace in target INI file if replacement value is defined | |
if key in keys: | |
line = "{}{}={}".format(commented, key, str(src_dict[key])) | |
src_dict.pop(key) | |
buffer.write(line + "\n") | |
# append any unreplaced key/values in as extra lines | |
for key in sorted(src_dict.keys()): | |
buffer.write(key + "=" + str(src_dict[key]) + "\n") | |
# write to disk | |
propfile.seek(0) | |
propfile.write(buffer.getvalue()) | |
def main(): | |
"""Main function""" | |
data = decode(sys.argv[1]) | |
result = {"msg": "OK"} | |
# basic checking | |
try: | |
if not data: | |
raise Exception("JSON data not loaded!") | |
target = data.get("target") or data.get("dest") | |
props = data.get("props") | |
if target is None or props is None: | |
raise Exception("JSON data is missing 'target' or 'props' attributes!") | |
elif not isinstance(props, dict): | |
raise Exception("'props' is not a dict!") | |
elif not os.path.exists(target): | |
raise Exception("Target %s does not exist!" % target) | |
process(target, props) | |
result["msg"] = "Finished replacing " + target | |
except Exception as e: | |
result['failed'] = True | |
result['msg'] = str(e) | |
print(json.dumps(result)) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment