From 11cd9ea092473c6b00de08b55f20ec0bf930b256 Mon Sep 17 00:00:00 2001 From: Fridious Date: Sun, 25 Dec 2022 18:37:06 +0100 Subject: [PATCH 1/5] Added .idea/ folder for IntelliJ to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 7f6b817..e25f241 100644 --- a/.gitignore +++ b/.gitignore @@ -129,3 +129,6 @@ dmypy.json .pyre/ .DS_Store + +# IntelliJ +.idea/ \ No newline at end of file From 3c6630966f25cd6008d9312bbac22906925ad3e3 Mon Sep 17 00:00:00 2001 From: Fridious Date: Sun, 25 Dec 2022 18:37:34 +0100 Subject: [PATCH 2/5] Updated cloudflare lib version to 2.11.1 --- requirements.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 1fb6f60..94bedd7 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,3 +1,3 @@ -cloudflare==2.9.11 +cloudflare==2.11.1 Flask==2.2.2 waitress==2.1.2 From ec38024ed7041068c2c4012b38d0afd6a56d3b07 Mon Sep 17 00:00:00 2001 From: Fridious Date: Sun, 25 Dec 2022 18:38:25 +0100 Subject: [PATCH 3/5] Added support to update multiple records per request --- app.py | 54 +++++++++++++++++++++++++++++++++--------------------- 1 file changed, 33 insertions(+), 21 deletions(-) diff --git a/app.py b/app.py index 9f210d9..a3ddde0 100644 --- a/app.py +++ b/app.py @@ -3,7 +3,6 @@ import waitress import flask - app = flask.Flask(__name__) @@ -12,6 +11,7 @@ def main(): token = flask.request.args.get('token') zone = flask.request.args.get('zone') record = flask.request.args.get('record') + records = flask.request.args.get('records') ipv4 = flask.request.args.get('ipv4') ipv6 = flask.request.args.get('ipv6') cf = CloudFlare.CloudFlare(token=token) @@ -20,8 +20,8 @@ def main(): return flask.jsonify({'status': 'error', 'message': 'Missing token URL parameter.'}), 400 if not zone: return flask.jsonify({'status': 'error', 'message': 'Missing zone URL parameter.'}), 400 - if not record: - return flask.jsonify({'status': 'error', 'message': 'Missing record URL parameter.'}), 400 + if not record and not records: + return flask.jsonify({'status': 'error', 'message': 'Missing record or records URL parameter.'}), 400 if not ipv4 and not ipv6: return flask.jsonify({'status': 'error', 'message': 'Missing ipv4 or ipv6 URL parameter.'}), 400 @@ -31,24 +31,11 @@ def main(): if not zones: return flask.jsonify({'status': 'error', 'message': 'Zone {} does not exist.'.format(zone)}), 404 - a_record = cf.zones.dns_records.get(zones[0]['id'], params={ - 'name': '{}.{}'.format(record, zone), 'match': 'all', 'type': 'A'}) - aaaa_record = cf.zones.dns_records.get(zones[0]['id'], params={ - 'name': '{}.{}'.format(record, zone), 'match': 'all', 'type': 'AAAA'}) - - if ipv4 is not None and not a_record: - return flask.jsonify({'status': 'error', 'message': 'A record for {}.{} does not exist.'.format(record, zone)}), 404 - - if ipv6 is not None and not aaaa_record: - return flask.jsonify({'status': 'error', 'message': 'AAAA record for {}.{} does not exist.'.format(record, zone)}), 404 - - if ipv4 is not None and a_record[0]['content'] != ipv4: - cf.zones.dns_records.put(zones[0]['id'], a_record[0]['id'], data={ - 'name': a_record[0]['name'], 'type': 'A', 'content': ipv4, 'proxied': a_record[0]['proxied'], 'ttl': a_record[0]['ttl']}) - - if ipv6 is not None and aaaa_record[0]['content'] != ipv6: - cf.zones.dns_records.put(zones[0]['id'], aaaa_record[0]['id'], data={ - 'name': aaaa_record[0]['name'], 'type': 'AAAA', 'content': ipv6, 'proxied': aaaa_record[0]['proxied'], 'ttl': aaaa_record[0]['ttl']}) + # put + if record: + put_dns_record(cf, zones, record, zone, ipv4, ipv6) + for r in records: + put_dns_record(cf, zones, r, zone, ipv4, ipv6) except CloudFlare.exceptions.CloudFlareAPIError as e: return flask.jsonify({'status': 'error', 'message': str(e)}), 500 @@ -60,5 +47,30 @@ def healthz(): return flask.jsonify({'status': 'success', 'message': 'OK'}), 200 +def put_dns_record(cf, zones, record, zone, ipv4, ipv6): + a_record = cf.zones.dns_records.get(zones[0]['id'], params={ + 'name': '{}.{}'.format(record, zone), 'match': 'all', 'type': 'A'}) + aaaa_record = cf.zones.dns_records.get(zones[0]['id'], params={ + 'name': '{}.{}'.format(record, zone), 'match': 'all', 'type': 'AAAA'}) + + if ipv4 is not None and not a_record: + return flask.jsonify( + {'status': 'error', 'message': 'A record for {}.{} does not exist.'.format(record, zone)}), 404 + + if ipv6 is not None and not aaaa_record: + return flask.jsonify( + {'status': 'error', 'message': 'AAAA record for {}.{} does not exist.'.format(record, zone)}), 404 + + if ipv4 is not None and a_record[0]['content'] != ipv4: + cf.zones.dns_records.put(zones[0]['id'], a_record[0]['id'], data={ + 'name': a_record[0]['name'], 'type': 'A', 'content': ipv4, 'proxied': a_record[0]['proxied'], + 'ttl': a_record[0]['ttl']}) + + if ipv6 is not None and aaaa_record[0]['content'] != ipv6: + cf.zones.dns_records.put(zones[0]['id'], aaaa_record[0]['id'], data={ + 'name': aaaa_record[0]['name'], 'type': 'AAAA', 'content': ipv6, 'proxied': aaaa_record[0]['proxied'], + 'ttl': aaaa_record[0]['ttl']}) + + app.secret_key = os.urandom(24) waitress.serve(app, host='0.0.0.0', port=80) From e12fa45de2889408738c4f838c4914689d23adaa Mon Sep 17 00:00:00 2001 From: Fridious Date: Sun, 25 Dec 2022 18:45:29 +0100 Subject: [PATCH 4/5] Added support to run github actions manually --- .github/workflows/docker-build-push.yml | 4 +++- .github/workflows/helmchart-push.yml | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/.github/workflows/docker-build-push.yml b/.github/workflows/docker-build-push.yml index c95e5d2..6c44e6e 100644 --- a/.github/workflows/docker-build-push.yml +++ b/.github/workflows/docker-build-push.yml @@ -1,5 +1,7 @@ name: Build and push Docker images to GitHub Packages -on: push +on: + push: + workflow_dispatch: jobs: cloudflare_dyndns_docker-build-push: name: Build and push cloudflare-dyndns docker image diff --git a/.github/workflows/helmchart-push.yml b/.github/workflows/helmchart-push.yml index 59ce1be..dea49a6 100644 --- a/.github/workflows/helmchart-push.yml +++ b/.github/workflows/helmchart-push.yml @@ -1,5 +1,7 @@ name: Build and push helm chart to GitHub Packages -on: push +on: + push: + workflow_dispatch: jobs: cloudflare_dyndns_helmchart-push: name: Push cloudflare-dyndns helm chart From 1104aeab37870fd89525a90d2d3a9a1b39d5cc3e Mon Sep 17 00:00:00 2001 From: Fridious Date: Sun, 25 Dec 2022 23:40:09 +0100 Subject: [PATCH 5/5] Fixed record updating for param records --- app.py | 63 +++++++++++++++++++++++++++++----------------------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/app.py b/app.py index a3ddde0..6f85fd3 100644 --- a/app.py +++ b/app.py @@ -25,19 +25,17 @@ def main(): if not ipv4 and not ipv6: return flask.jsonify({'status': 'error', 'message': 'Missing ipv4 or ipv6 URL parameter.'}), 400 - try: - zones = cf.zones.get(params={'name': zone}) + zones = cf.zones.get(params={'name': zone}) - if not zones: - return flask.jsonify({'status': 'error', 'message': 'Zone {} does not exist.'.format(zone)}), 404 + if not zones: + return flask.jsonify({'status': 'error', 'message': 'Zone {} does not exist.'.format(zone)}), 404 - # put - if record: - put_dns_record(cf, zones, record, zone, ipv4, ipv6) + if record: + put_dns_record(cf, zones, record, zone, ipv4, ipv6) + if records: + records = records.split(",") for r in records: put_dns_record(cf, zones, r, zone, ipv4, ipv6) - except CloudFlare.exceptions.CloudFlareAPIError as e: - return flask.jsonify({'status': 'error', 'message': str(e)}), 500 return flask.jsonify({'status': 'success', 'message': 'Update successful.'}), 200 @@ -48,28 +46,31 @@ def healthz(): def put_dns_record(cf, zones, record, zone, ipv4, ipv6): - a_record = cf.zones.dns_records.get(zones[0]['id'], params={ - 'name': '{}.{}'.format(record, zone), 'match': 'all', 'type': 'A'}) - aaaa_record = cf.zones.dns_records.get(zones[0]['id'], params={ - 'name': '{}.{}'.format(record, zone), 'match': 'all', 'type': 'AAAA'}) - - if ipv4 is not None and not a_record: - return flask.jsonify( - {'status': 'error', 'message': 'A record for {}.{} does not exist.'.format(record, zone)}), 404 - - if ipv6 is not None and not aaaa_record: - return flask.jsonify( - {'status': 'error', 'message': 'AAAA record for {}.{} does not exist.'.format(record, zone)}), 404 - - if ipv4 is not None and a_record[0]['content'] != ipv4: - cf.zones.dns_records.put(zones[0]['id'], a_record[0]['id'], data={ - 'name': a_record[0]['name'], 'type': 'A', 'content': ipv4, 'proxied': a_record[0]['proxied'], - 'ttl': a_record[0]['ttl']}) - - if ipv6 is not None and aaaa_record[0]['content'] != ipv6: - cf.zones.dns_records.put(zones[0]['id'], aaaa_record[0]['id'], data={ - 'name': aaaa_record[0]['name'], 'type': 'AAAA', 'content': ipv6, 'proxied': aaaa_record[0]['proxied'], - 'ttl': aaaa_record[0]['ttl']}) + try: + a_record = cf.zones.dns_records.get(zones[0]['id'], params={ + 'name': '{}.{}'.format(record, zone), 'match': 'all', 'type': 'A'}) + aaaa_record = cf.zones.dns_records.get(zones[0]['id'], params={ + 'name': '{}.{}'.format(record, zone), 'match': 'all', 'type': 'AAAA'}) + + if ipv4 is not None and not a_record: + return flask.jsonify( + {'status': 'error', 'message': 'A record for {}.{} does not exist.'.format(record, zone)}), 404 + + if ipv6 is not None and not aaaa_record: + return flask.jsonify( + {'status': 'error', 'message': 'AAAA record for {}.{} does not exist.'.format(record, zone)}), 404 + + if ipv4 is not None and a_record[0]['content'] != ipv4: + cf.zones.dns_records.put(zones[0]['id'], a_record[0]['id'], data={ + 'name': a_record[0]['name'], 'type': 'A', 'content': ipv4, 'proxied': a_record[0]['proxied'], + 'ttl': a_record[0]['ttl']}) + + if ipv6 is not None and aaaa_record[0]['content'] != ipv6: + cf.zones.dns_records.put(zones[0]['id'], aaaa_record[0]['id'], data={ + 'name': aaaa_record[0]['name'], 'type': 'AAAA', 'content': ipv6, 'proxied': aaaa_record[0]['proxied'], + 'ttl': aaaa_record[0]['ttl']}) + except CloudFlare.exceptions.CloudFlareAPIError as e: + return flask.jsonify({'status': 'error', 'message': str(e)}), 500 app.secret_key = os.urandom(24)