Playbooks to a new Lilik
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

148 lines
3.5 KiB

  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. DOCUMENTATION = '''
  4. ---
  5. module: json_file
  6. author: Daniele Baracchi
  7. short_description: Manipulate json files
  8. description:
  9. - Manipulate json files
  10. options:
  11. path:
  12. required: true
  13. description:
  14. - Path to the JSON file to be manipulated.
  15. key:
  16. required: true
  17. description:
  18. - Key to be checked.
  19. value:
  20. required: false
  21. description:
  22. - Value to set the key to.
  23. state:
  24. required: false
  25. default: "present"
  26. choices: [ "present", "absent" ]
  27. description:
  28. - Whether the key should exist or not, taking action if the state is different from what is stated.
  29. '''
  30. import json
  31. import os.path
  32. from ansible.module_utils.basic import *
  33. class JsonFile(object):
  34. def __init__(self, path):
  35. self.path = path
  36. with open(path, 'r') as stream:
  37. self.contents = json.load(stream)
  38. def has_key(self, key):
  39. key_path = key.split('.')
  40. container = self.contents
  41. for part in key_path:
  42. if part in container:
  43. container = container[part]
  44. else:
  45. return False
  46. return True
  47. def has_pair(self, key, value):
  48. key_path = key.split('.')
  49. container = self.contents
  50. for part in key_path:
  51. if part in container:
  52. container = container[part]
  53. else:
  54. return False
  55. return container == value
  56. def drop_key(self, key):
  57. key_path = key.split('.')
  58. container = self.contents
  59. for part in key_path[:-1]:
  60. container = container[part]
  61. del container[key_path[-1]]
  62. def set_key(self, key, value):
  63. key_path = key.split('.')
  64. container = self.contents
  65. for part in key_path[:-1]:
  66. if part not in container:
  67. container[part] = {}
  68. container = container[part]
  69. container[key_path[-1]] = value
  70. def serialize(self):
  71. with open(self.path, 'w') as stream:
  72. json.dump(self.contents, stream, indent=4)
  73. def main():
  74. module = AnsibleModule(
  75. argument_spec=dict(
  76. state=dict(default='present', choices=['present', 'absent'],
  77. type='str'),
  78. path=dict(required=True, type='str'),
  79. key=dict(required=True, type='str'),
  80. value=dict(default=None, type='str')
  81. ),
  82. supports_check_mode=True
  83. )
  84. path = module.params.get('path')
  85. key = module.params.get('key')
  86. state = module.params.get('state')
  87. result = {}
  88. result['path'] = path
  89. result['key'] = key
  90. result['state'] = state
  91. if not os.path.exists(path):
  92. module.fail_json("File not found: %s" % path)
  93. the_file = JsonFile(path)
  94. if state == 'absent':
  95. if the_file.has_key(key):
  96. if module.check_mode:
  97. module.exit_json(changed=True)
  98. else:
  99. the_file.drop_key(key)
  100. the_file.serialize()
  101. result['changed'] = True
  102. elif state == 'present':
  103. value = module.params.get('value')
  104. result['value'] = value
  105. if not the_file.has_pair(key, value):
  106. if module.check_mode:
  107. module.exit_json(changed=True)
  108. else:
  109. the_file.set_key(key, value)
  110. the_file.serialize()
  111. result['changed'] = True
  112. module.exit_json(**result)
  113. if __name__ == '__main__':
  114. main()