#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright: (c) 2018, Rafael Bodill # Copyright: (c) 2020, Borjan Tchakaloff # GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt) ANSIBLE_METADATA = { 'metadata_version': '1.1', 'status': ['preview'], 'supported_by': 'community' } DOCUMENTATION = ''' --- module: folder_defaults short_description: Manage Syncthing folder default configurations version_added: "2.7" description: - "This module allows you to manage Syncthing folder default configurations. You can update the default configurations using this module. It uses the Syncthing REST API to perform these operations." options: id: description: - The ID of the module. type: str required: false label: description: - The label for the module. type: str required: false filesystemType: description: - The filesystem type for the module. type: str required: false default: basic path: description: - The path for the module. type: str required: false default: ~ type: description: - The type of the module. type: str required: false default: sendreceive choices: [sendreceive, sendonly, receiveonly] devices: description: - List of devices for the module. type: list required: false default: [] rescanIntervalS: description: - The rescan interval for the module in seconds. type: int required: false default: 3600 fsWatcherEnabled: description: - Whether the filesystem watcher is enabled for the module. type: bool required: false default: true fsWatcherDelayS: description: - The filesystem watcher delay for the module in seconds. type: int required: false default: 10 ignorePerms: description: - Whether to ignore permissions for the module. type: bool required: false default: false autoNormalize: description: - Whether to automatically normalize for the module. type: bool required: false default: true minDiskFree: description: - The minimum disk free for the module. type: dict required: false default: {value: 1, unit: '%'} versioning: description: - The versioning for the module. type: dict required: false default: {type: '', params: {}, cleanupIntervalS: 3600, fsPath: '', fsType: 'basic'} copiers: description: - The number of copiers for the module. type: int required: false default: 0 pullerMaxPendingKiB: description: - The maximum pending puller size for the module in KiB. type: int required: false default: 0 hashers: description: - The number of hashers for the module. type: int required: false default: 0 order: description: - The order for the module. type: str required: false default: random ignoreDelete: description: - Whether to ignore delete for the module. type: bool required: false default: false scanProgressIntervalS: description: - The scan progress interval for the module in seconds. type: int required: false default: 0 pullerPauseS: description: - The puller pause for the module in seconds. type: int required: false default: 0 maxConflicts: description: - The maximum number of conflicts for the module. type: int required: false default: 10 disableSparseFiles: description: - Whether to disable sparse files for the module. type: bool required: false default: false disableTempIndexes: description: - Whether to disable temporary indexes for the module. type: bool required: false default: false paused: description: - Whether the module is paused. type: bool required: false default: false weakHashThresholdPct: description: - The weak hash threshold for the module in percentage. type: int required: false default: 25 markerName: description: - The marker name for the module. type: str required: false default: .stfolder copyOwnershipFromParent: description: - Whether to copy ownership from parent for the module. type: bool required: false default: false modTimeWindowS: description: - The modification time window for the module in seconds. type: int required: false default: 0 maxConcurrentWrites: description: - The maximum number of concurrent writes for the module. type: int required: false default: 2 disableFsync: description: - Whether to disable fsync for the module. type: bool required: false default: false blockPullOrder: description: - The block pull order for the module. type: str required: false default: standard copyRangeMethod: description: - The copy range method for the module. type: str required: false default: standard caseSensitiveFS: description: - Whether the filesystem is case sensitive for the module. type: bool required: false default: false junctionsAsDirs: description: - Whether to treat junctions as directories for the module. type: bool required: false default: false syncOwnership: description: - Whether to synchronize ownership for the module. type: bool required: false default: false sendOwnership: description: - Whether to send ownership for the module. type: bool required: false default: false syncXattrs: description: - Whether to synchronize extended attributes for the module. type: bool required: false default: false sendXattrs: description: - Whether to send extended attributes for the module. type: bool required: false default: false xattrFilter: description: - The extended attribute filter for the module. type: dict required: false default: {entries: [], maxSingleEntrySize: 1024, maxTotalSize: 4096} author: - Rafael Bodill (@rafi) ''' EXAMPLES = ''' # Get/Update folder_defaults - name: Get folder_defaults become: yes become_user: syncthing community.syncthing.folder_defaults: host: http://localhost unix_socket: /run/syncthing/syncthing.sock config_file: /var/lib/syncthing/.config/syncthing/config.xml id: "default" label: "default" path: "/" paused: false register: folder_defaults ''' RETURN = ''' folder_defaults: description: The default configuration of the folder after the operation. type: dict changed: description: Whether any changes were made. type: bool response: description: The API response, in-case of an error. type: dict ''' from ansible_collections.community.syncthing.plugins.module_utils.syncthing_api import SyncthingModule import json def deep_equal(a, b): return json.dumps(a, sort_keys=True) == json.dumps(b, sort_keys=True) def run_module(): module_args = dict( id=dict(type='str', required=False), label=dict(type='str', required=False), filesystemType=dict(type='str', required=False, default='basic'), path=dict(type='str', required=False, default='~'), type=dict(type='str', default='sendreceive', choices=['sendreceive', 'sendonly', 'receiveonly']), devices=dict(type='list', required=False, default=[]), rescanIntervalS=dict(type='int', required=False, default=3600), fsWatcherEnabled=dict(type='bool', required=False, default=True), fsWatcherDelayS=dict(type='int', required=False, default=10), ignorePerms=dict(type='bool', required=False, default=False), autoNormalize=dict(type='bool', required=False, default=True), minDiskFree=dict(type='dict', required=False, default=dict(value=1, unit='%')), versioning=dict(type='dict', required=False, default=dict(type='', params={}, cleanupIntervalS=3600, fsPath='', fsType='basic')), copiers=dict(type='int', required=False, default=0), pullerMaxPendingKiB=dict(type='int', required=False, default=0), hashers=dict(type='int', required=False, default=0), order=dict(type='str', required=False, default='random'), ignoreDelete=dict(type='bool', required=False, default=False), scanProgressIntervalS=dict(type='int', required=False, default=0), pullerPauseS=dict(type='int', required=False, default=0), maxConflicts=dict(type='int', required=False, default=10), disableSparseFiles=dict(type='bool', required=False, default=False), disableTempIndexes=dict(type='bool', required=False, default=False), paused=dict(type='bool', required=False, default=False), weakHashThresholdPct=dict(type='int', required=False, default=25), markerName=dict(type='str', required=False, default='.stfolder'), copyOwnershipFromParent=dict(type='bool', required=False, default=False), modTimeWindowS=dict(type='int', required=False, default=0), maxConcurrentWrites=dict(type='int', required=False, default=2), disableFsync=dict(type='bool', required=False, default=False), blockPullOrder=dict(type='str', required=False, default='standard'), copyRangeMethod=dict(type='str', required=False, default='standard'), caseSensitiveFS=dict(type='bool', required=False, default=False), junctionsAsDirs=dict(type='bool', required=False, default=False), syncOwnership=dict(type='bool', required=False, default=False), sendOwnership=dict(type='bool', required=False, default=False), syncXattrs=dict(type='bool', required=False, default=False), sendXattrs=dict(type='bool', required=False, default=False), xattrFilter=dict(type='dict', required=False, default=dict(entries=[], maxSingleEntrySize=1024, maxTotalSize=4096)), ) module = SyncthingModule( api_url='/rest/config/defaults/folder', argument_spec=module_args, ) current_config = module.get_call() module_args_keys_list = list(module_args.keys()) changes = {} for key, value in module.params.items(): # Check if the key is in module_args_keys_list if key in module_args_keys_list: # Check if the value is not None if value is not None: # Check if the value is different from the current_config if not deep_equal(value, current_config.get(key)): # If all conditions are met, add the key-value pair to changes changes[key] = value if module.check_mode or len(changes.keys()) == 0: module.result['folder_defaults'] = current_config module.exit_json() module.patch_call(data=module.params) module.result['folder_defaults'] = module.get_call() module.result['changed'] = True module.result['changes'] = changes module.exit_json() def main(): run_module() if __name__ == '__main__': main()