#!/usr/bin/env python3 from ansible.module_utils.basic import AnsibleModule import subprocess import sys # Auto-Install, falls caldav fehlt try: from caldav import DAVClient import vobject except ImportError: subprocess.check_call([sys.executable, "-m", "pip", "install", "caldav", "vobject"]) from caldav import DAVClient import vobject def connect_calendar(url, user=None, password=None): client = DAVClient(url, username=user, password=password) if user else DAVClient(url) principal = client.principal() calendars = principal.calendars() if not calendars: raise Exception(f"Kein Kalender gefunden unter {url}") return calendars[0] def get_event_uid_map(calendar): uid_map = {} for event in calendar.events(): try: cal = vobject.readOne(event.data) uid = cal.vevent.uid.value uid_map[uid] = event except Exception: continue return uid_map def sync_calendars(source_cal, target_cal): src_events = get_event_uid_map(source_cal) tgt_events = get_event_uid_map(target_cal) changed = False added, updated, removed = [], [], [] for uid, src_event in src_events.items(): src_data = src_event.data if uid not in tgt_events: target_cal.add_event(src_data) added.append(uid) changed = True elif src_data != tgt_events[uid].data: tgt_events[uid].delete() target_cal.add_event(src_data) updated.append(uid) changed = True for uid in set(tgt_events.keys()) - set(src_events.keys()): tgt_events[uid].delete() removed.append(uid) changed = True return changed, added, updated, removed def run_module(): module_args = dict( source_url=dict(type='str', required=True), source_user=dict(type='str', required=False, default=None), source_password=dict(type='str', required=False, default=None, no_log=True), target_url=dict(type='str', required=True), target_user=dict(type='str', required=True), target_password=dict(type='str', required=True, no_log=True), ) result = dict( changed=False, added=[], updated=[], removed=[], ) module = AnsibleModule(argument_spec=module_args, supports_check_mode=False) try: source_cal = connect_calendar( module.params['source_url'], module.params['source_user'], module.params['source_password'] ) target_cal = connect_calendar( module.params['target_url'], module.params['target_user'], module.params['target_password'] ) changed, added, updated, removed = sync_calendars(source_cal, target_cal) result['changed'] = changed result['added'] = added result['updated'] = updated result['removed'] = removed module.exit_json(**result) except Exception as e: module.fail_json(msg=str(e), **result) def main(): run_module() if __name__ == '__main__': main()