Add ability to update CloudFlare worker with list of mailing lists

This commit is contained in:
Adam Goldsmith 2023-09-02 22:14:02 -04:00
parent 51439a54c2
commit b7043750bb

View File

@ -17,6 +17,7 @@ Update Mailman 3 lists via a json API of the form:
""" """
import argparse import argparse
import json
import os import os
import email.utils import email.utils
@ -120,12 +121,56 @@ def sync_moderators(
list.remove_moderator(member.address) list.remove_moderator(member.address)
def update_cloudflare_lists(
dry_run: bool,
auth_token: str,
account_id: str,
script_name: str,
binding_name: str,
expected: list[str],
):
settings_api_url = f"https://api.cloudflare.com/client/v4/accounts/{account_id}/workers/scripts/{script_name}/settings"
r = requests.get(
settings_api_url,
headers={"Authorization": auth_token},
)
data = r.json()
# TODO: more error handling
if not data["success"]:
print("Failed to fetch Cloudflare email worker settings")
bindings_dict = {b["name"]: b for b in data["result"]["bindings"]}
if set(bindings_dict.get(binding_name, {}).get("json", [])) != set(expected):
print("Cloudflare email worker list out of date, updating")
bindings_dict[binding_name] = {
"name": binding_name,
"json": expected,
"type": "json",
}
if not dry_run:
r = requests.patch(
settings_api_url,
headers={"Authorization": auth_token},
files={
"settings": json.dumps({"bindings": list(bindings_dict.values())}),
},
)
else:
print("Cloudflare email worker list already up to date")
def main( def main(
api: str, api: str,
api_auth: str, api_auth: str,
mailman_client: mailmanclient.Client, mailman_client: mailmanclient.Client,
dry_run: bool, dry_run: bool,
mail_host: str, mail_host: str,
cf_auth_token: str,
cf_account_id: str,
cf_script_name: str,
cf_binding_name: str,
): ):
r = requests.get(api, headers={"Authorization": api_auth}) r = requests.get(api, headers={"Authorization": api_auth})
if not r.ok: if not r.ok:
@ -155,10 +200,16 @@ def main(
sync_moderators(list, dry_run, props["moderators"]) sync_moderators(list, dry_run, props["moderators"])
sync_members(list, dry_run, props["members"]) sync_members(list, dry_run, props["members"])
lists = [list.list_name.lower() for list in domain.get_lists()]
update_cloudflare_lists(
dry_run, cf_auth_token, cf_account_id, cf_script_name, cf_binding_name, lists
)
def parse_arguments(): def parse_arguments():
argp = argparse.ArgumentParser(description=__doc__) argp = argparse.ArgumentParser(description=__doc__)
argp.add_argument("--api", required=True, help="API endpoint to retrieve JSON from") argp.add_argument("--api", required=True, help="API endpoint to retrieve JSON from")
argp.add_argument("--mail-host", help="Base domain for all lists", required=True) argp.add_argument("--mail-host", help="Base domain for all lists", required=True)
argp.add_argument( argp.add_argument(
"--mailman-url", "--mailman-url",
@ -168,6 +219,24 @@ def parse_arguments():
argp.add_argument( argp.add_argument(
"--mailman-user", help="Username for Mailman3 REST API", default="restadmin" "--mailman-user", help="Username for Mailman3 REST API", default="restadmin"
) )
argp.add_argument(
"--cf-auth-token", help="Auth token for CloudFlare API", required=True
)
argp.add_argument(
"--cf-account-id",
help="Account ID of CloudFlare email worker script",
required=True,
)
argp.add_argument(
"--cf-script-name", help="Name of CloudFlare email worker script", required=True
)
argp.add_argument(
"--cf-binding-name",
help="Name of environment variable in email worker script",
default="MAILMAN_LISTS",
)
argp.add_argument( argp.add_argument(
"-n", "-n",
"--dry-run", "--dry-run",
@ -197,4 +266,8 @@ if __name__ == "__main__":
mailman_client, mailman_client,
args.dry_run, args.dry_run,
args.mail_host, args.mail_host,
args.cf_auth_token,
args.cf_account_id,
args.cf_script_name,
args.cf_binding_name,
) )